Example #1
0
int
scope6_get(struct ifnet *ifp, struct scope6_id *idlist)
{
	struct scope6_id *sid;

	/* We only need to lock the interface's afdata for SID() to work. */
	IF_AFDATA_RLOCK(ifp);
	sid = SID(ifp);
	if (sid == NULL) {	/* paranoid? */
		IF_AFDATA_RUNLOCK(ifp);
		return (EINVAL);
	}

	*idlist = *sid;

	IF_AFDATA_RUNLOCK(ifp);
	return (0);
}
Example #2
0
/*
 * Determine the appropriate scope zone ID for in6 and ifp.  If ret_id is
 * non NULL, it is set to the zone ID.  If the zone ID needs to be embedded
 * in the in6_addr structure, in6 will be modified.
 *
 * ret_id - unnecessary?
 */
int
in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
{
	int scope;
	u_int32_t zoneid = 0;
	struct scope6_id *sid;

	/*
	 * special case: the loopback address can only belong to a loopback
	 * interface.
	 */
	if (IN6_IS_ADDR_LOOPBACK(in6)) {
		if (!(ifp->if_flags & IFF_LOOPBACK))
			return (EINVAL);
	} else {
		scope = in6_addrscope(in6);
		if (scope == IPV6_ADDR_SCOPE_INTFACELOCAL ||
		    scope == IPV6_ADDR_SCOPE_LINKLOCAL) {
			/*
			 * Currently we use interface indeces as the
			 * zone IDs for interface-local and link-local
			 * scopes.
			 */
			zoneid = ifp->if_index;
			in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
		} else if (scope != IPV6_ADDR_SCOPE_GLOBAL) {
			IF_AFDATA_RLOCK(ifp);
			sid = SID(ifp);
			zoneid = sid->s6id_list[scope];
			IF_AFDATA_RUNLOCK(ifp);
		}
	}

	if (ret_id != NULL)
		*ret_id = zoneid;

	return (0);
}
Example #3
0
/*
 * Original (hw independent) Link layer output routine is wrapped by 
 * mpls_output, if focussed Link layer interface remains in MPLS enabled 
 * state. Original output routine is hooked by mpls_ifinfo{} and called 
 * by mpls_output.
 *
 * Any by protocol layer above transmitted mbuf(9) containing Protocol 
 * Data Uniit (pdu) must pass MPLS layer, if for transmission used interface
 * on link-layer remains in MPLS enabled state. 
 * 
 * I/O Path, IPv4:
 *
 *              rip_input() +{ socket layer }+ rip_output()
 *                         /                  \
 *                        /                    \
 *      +-->+ ip_input() +-->+ ip_forward() +-->+ ip_output()
 *     /     \                                   \
 *    /       \                                   +
 *   +         +<------+                          |
 *   |                  \                         v 
 *   + mpls_input() +--->+ mpls_forward() +------>+ mpls_output()			
 *   |\                                          /|
 *   | \                               +<-------+ |
 *   |  \                             /           |
 *   |   +<-----------+ if_simloop() +<-----------+ if_output()
 *   |                                            |
 *   + if_input()                                 |
 *   A                                            |
 *   |                                            V
 *
 */
int
mpls_output(struct ifnet *ifp, struct mbuf *m, 
		const struct sockaddr *dst, struct route *ro)
{	
	struct mpls_ifinfo *mii;
	struct mpls_ro mplsroute;
	struct mpls_ro *mro;
	struct sockaddr *gw;
	
	int error = 0;
	
#ifdef MPLS_DEBUG
	struct shim_hdr *shim;
#endif /* MPLS_DEBUG */ 	
	
	if ((ifp->if_flags & IFF_MPLS) == 0) {
/*
 * Any pdu originates MPLS-layer are looped back into its 
 * domain, if for transmission used interface cannot accept 
 * by MPLS-layer processed pdu.
 *
 * See net/if_ethersubr.c and net/if_loop.c for further details.
 */
		if (dst->sa_family == AF_MPLS) 
			if_simloop(ifp, m, dst->sa_family, 0);
		else 
			error = (*ifp->if_output)(ifp, m, dst, ro);
		goto out;
	}	
	IF_AFDATA_RLOCK(ifp);
	mii = MPLS_IFINFO(ifp);
	IF_AFDATA_RUNLOCK(ifp);
	
	mro = &mplsroute;
	bzero(mro, sizeof(*mro));
	
	if (ro == NULL) 
		ro = (struct route *)mro;	

	if (ro->ro_rt != NULL) {
/*
 * If route exists, three cases are considered:
 * 
 *  (a) held route denotes fastpath. 
 *  (b) held route denotes ilm,
 *
 * or
 *  
 *  (c) held route originates not AF_MPLS domain.
 */
		if (ro->ro_rt->rt_flags & RTF_MPE) { 
			gw = ro->ro_rt->rt_gateway;
			
			if ((m = mpls_encap(m, gw, mro)) == NULL) {
				error = ECONNABORTED;
				goto done;
			}
			gw = (struct sockaddr *)&mro->mro_gw;
		} else
			gw = (struct sockaddr *)dst;		
	} else
		gw = (struct sockaddr *)dst;
	
	if (m->m_flags & M_MPLS) {
/*
 * Bypass tagging, if mbuf(9) was cached by MPLS_ARP.
 */
		m->m_flags &= ~M_MPLS;
	} else if (mii->mii_nhlfe != NULL) {
/*
 * Otherwise, mbuf(9) must pass mpls_encap, if 
 * interface is bound by MPLS label binding on
 * per-interface MPLS label space.  
 */	
		mro->mro_ifa = mii->mii_nhlfe;
		gw = mro->mro_ifa->ifa_dstaddr;
/*
 * Per interface MPLS label space.
 */					
		if ((m = mpls_encap(m, gw, mro)) == NULL) {
			error = ECONNABORTED;
			goto done;
		}
		gw = (struct sockaddr *)&mro->mro_gw;
	}
	
	if (gw->sa_family == AF_MPLS) {
/* 
 * Defines iap for pfil(9) processing.
 */
		if (PFIL_HOOKED(&V_inet_pfil_hook)
#ifdef INET6
	    	|| PFIL_HOOKED(&V_inet6_pfil_hook)
#endif
	    ) {		
			if (mpls_pfil(&m, ifp, PFIL_OUT) != 0)
				goto done;
				
			if (m == NULL)
				goto done;
		}
		
#ifdef MPLS_DEBUG
	shim = mtod(m, struct shim_hdr *);
	(void)printf("%s: on %s label %d ttl %d bos %d\n", 
		__func__, ifp->if_xname, 
		MPLS_LABEL_GET(shim->shim_label), 
		MPLS_TTL_GET(shim->shim_label), 
		MPLS_BOS(shim->shim_label));
#endif /* MPLS_DEBUG */	

		m->m_flags &= ~(M_BCAST|M_MCAST);
	}
	error = (*mii->mii_output)(ifp, m, gw, ro);
done:	
	if (mro != NULL)
		mpls_rtfree(mro);
out:	
	return (error);
}