FreeBSD/sys/net/if_tun.c
/*
 * tunoutput - queue packets from higher level ready to put out.
 */
queue packets from higher level ready to put out.
queue packets from higher level ready to put out .
static int
tunoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
    struct route *ro)
{
	struct tun_softc *tp = ifp->if_softc;
	u_short cached_tun_flags;
	int error;
	u_int32_t af;
	TUNDEBUG (ifp, "tunoutput\n");
#ifdef MAC
	error = mac_ifnet_check_transmit(ifp, m0);
	if (error) {
		m_freem(m0);
		return (error);
	}
#endif
	mtx_lock(&tp->tun_mtx);
	cached_tun_flags = tp->tun_flags;
	mtx_unlock(&tp->tun_mtx);
	if ((cached_tun_flags & TUN_READY) != TUN_READY) {
		TUNDEBUG (ifp, "not ready 0%o\n", tp->tun_flags);
		m_freem (m0);
		return (EHOSTDOWN);
	}
	if ((ifp->if_flags & IFF_UP) != IFF_UP) {
		m_freem (m0);
		return (EHOSTDOWN);
	}
	if (dst->sa_family == AF_UNSPEC)
		bcopy(dst->sa_data, &af, sizeof(af));
	else
		af = dst->sa_family;
	if (bpf_peers_present(ifp->if_bpf))
		bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m0);
	if (cached_tun_flags & TUN_LMODE) {
		M_PREPEND(m0, dst->sa_len, M_NOWAIT);
		if (m0 == NULL) {
			if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
			return (ENOBUFS);
		} else {
			bcopy(dst, m0->m_data, dst->sa_len);
		}
	}
	if (cached_tun_flags & TUN_IFHEAD) {
		M_PREPEND(m0, 4, M_NOWAIT);
		if (m0 == NULL) {
			if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
			return (ENOBUFS);
		} else
			*(u_int32_t *)m0->m_data = htonl(af);
	} else {
#ifdef INET
		if (af != AF_INET)
#endif
		{
			m_freem(m0);
			return (EAFNOSUPPORT);
		}
	}
	error = (ifp->if_transmit)(ifp, m0);
	if (error)
		return (ENOBUFS);
	if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
	return (0);
}
static int tunoutput ( struct ifnet * ifp , struct mbuf * m0 , const struct sockaddr * dst , struct route * ro ) { struct tun_softc * tp = ifp -> if_softc ; u_short cached_tun_flags ; int error ; u_int32_t af ; TUNDEBUG ( ifp , " \n " ) ; #ifdef MAC error = mac_ifnet_check_transmit ( ifp , m0 ) ; if ( error ) { m_freem ( m0 ) ; return ( error ) ; } #endif mtx_lock ( & tp -> tun_mtx ) ; cached_tun_flags = tp -> tun_flags ; mtx_unlock ( & tp -> tun_mtx ) ; if ( ( cached_tun_flags & TUN_READY ) != TUN_READY ) { TUNDEBUG ( ifp , " \n " , tp -> tun_flags ) ; m_freem ( m0 ) ; return ( EHOSTDOWN ) ; } if ( ( ifp -> if_flags & IFF_UP ) != IFF_UP ) { m_freem ( m0 ) ; return ( EHOSTDOWN ) ; } if ( dst -> sa_family == AF_UNSPEC ) bcopy ( dst -> sa_data , & af , sizeof ( af ) ) ; else af = dst -> sa_family ; if ( bpf_peers_present ( ifp -> if_bpf ) ) bpf_mtap2 ( ifp -> if_bpf , & af , sizeof ( af ) , m0 ) ; if ( cached_tun_flags & TUN_LMODE ) { M_PREPEND ( m0 , dst -> sa_len , M_NOWAIT ) ; if ( m0 == NULL ) { if_inc_counter ( ifp , IFCOUNTER_IQDROPS , 1 ) ; if_inc_counter ( ifp , IFCOUNTER_OERRORS , 1 ) ; return ( ENOBUFS ) ; } else { bcopy ( dst , m0 -> m_data , dst -> sa_len ) ; } } if ( cached_tun_flags & TUN_IFHEAD ) { M_PREPEND ( m0 , 4 , M_NOWAIT ) ; if ( m0 == NULL ) { if_inc_counter ( ifp , IFCOUNTER_IQDROPS , 1 ) ; if_inc_counter ( ifp , IFCOUNTER_OERRORS , 1 ) ; return ( ENOBUFS ) ; } else * ( u_int32_t * ) m0 -> m_data = htonl ( af ) ; } else { #ifdef INET if ( af != AF_INET ) #endif { m_freem ( m0 ) ; return ( EAFNOSUPPORT ) ; } } error = ( ifp -> if_transmit ) ( ifp , m0 ) ; if ( error ) return ( ENOBUFS ) ; if_inc_counter ( ifp , IFCOUNTER_OPACKETS , 1 ) ; return ( 0 ) ; }
tunoutput - queue packets from higher level ready to put out.
tunoutput - queue packets from higher level ready to put out .
/* Could be unlocked read? */ /* BPF writes need to be handled specially. */ /* prepend sockaddr? this may abort if the mbuf allocation fails */ /* allocate space for sockaddr */ /* if allocation failed drop packet */ /* Prepend the address family */ /* if allocation failed drop packet */