FreeBSD/sys/netpfil/ipfw/ip_dn_io.c
/*
 * forward a chain of packets to the proper destination.
 * This runs outside the dummynet lock.
 */
forward a chain of packets to the proper destination.
This runs outside the dummynet lock.
forward a chain of packets to the proper destination . This runs outside the dummynet lock .
static void
dummynet_send(struct mbuf *m)
{
	struct mbuf *n;
	for (; m != NULL; m = n) {
		struct ifnet *ifp = NULL;	
        	struct m_tag *tag;
		int dst;
		n = m->m_nextpkt;
		m->m_nextpkt = NULL;
		tag = m_tag_first(m);
		if (tag == NULL) { 
			dst = DIR_DROP;
		} else {
			struct dn_pkt_tag *pkt = dn_tag_get(m);
			if (pkt->dn_dir == (DIR_OUT | PROTO_LAYER2) &&
				pkt->ifp == NULL) {
				dst = DIR_DROP;
			} else {
				dst = pkt->dn_dir;
				ifp = pkt->ifp;
				tag->m_tag_cookie = MTAG_IPFW_RULE;
				tag->m_tag_id = 0;
			}
		}
		switch (dst) {
		case DIR_OUT:
			ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
			break ;
		case DIR_IN :
			netisr_dispatch(NETISR_IP, m);
			break;
#ifdef INET6
		case DIR_IN | PROTO_IPV6:
			netisr_dispatch(NETISR_IPV6, m);
			break;
		case DIR_OUT | PROTO_IPV6:
			ip6_output(m, NULL, NULL, IPV6_FORWARDING, NULL, NULL, NULL);
			break;
#endif
		case DIR_FWD | PROTO_IFB: 
			if (bridge_dn_p != NULL)
				((*bridge_dn_p)(m, ifp));
			else
				printf("dummynet: if_bridge not loaded\n");
			break;
		case DIR_IN | PROTO_LAYER2: 
			if (m->m_len < ETHER_HDR_LEN &&
			    (m = m_pullup(m, ETHER_HDR_LEN)) == NULL) {
				printf("dummynet/ether: pullup failed, "
				    "dropping packet\n");
				break;
			}
			ether_demux(m->m_pkthdr.rcvif, m);
			break;
		case DIR_OUT | PROTO_LAYER2: 
			ether_output_frame(ifp, m);
			break;
		case DIR_DROP:
			FREE_PKT(m);
			break;
		default:
			printf("dummynet: bad switch %d!\n", dst);
			FREE_PKT(m);
			break;
		}
	}
}
static void dummynet_send ( struct mbuf * m ) { struct mbuf * n ; for ( ; m != NULL ; m = n ) { struct ifnet * ifp = NULL ; struct m_tag * tag ; int dst ; n = m -> m_nextpkt ; m -> m_nextpkt = NULL ; tag = m_tag_first ( m ) ; if ( tag == NULL ) { dst = DIR_DROP ; } else { struct dn_pkt_tag * pkt = dn_tag_get ( m ) ; if ( pkt -> dn_dir == ( DIR_OUT | PROTO_LAYER2 ) && pkt -> ifp == NULL ) { dst = DIR_DROP ; } else { dst = pkt -> dn_dir ; ifp = pkt -> ifp ; tag -> m_tag_cookie = MTAG_IPFW_RULE ; tag -> m_tag_id = 0 ; } } switch ( dst ) { case DIR_OUT : ip_output ( m , NULL , NULL , IP_FORWARDING , NULL , NULL ) ; break ; case DIR_IN : netisr_dispatch ( NETISR_IP , m ) ; break ; #ifdef INET6 case DIR_IN | PROTO_IPV6 : netisr_dispatch ( NETISR_IPV6 , m ) ; break ; case DIR_OUT | PROTO_IPV6 : ip6_output ( m , NULL , NULL , IPV6_FORWARDING , NULL , NULL , NULL ) ; break ; #endif case DIR_FWD | PROTO_IFB : if ( bridge_dn_p != NULL ) ( ( * bridge_dn_p ) ( m , ifp ) ) ; else printf ( " \n " ) ; break ; case DIR_IN | PROTO_LAYER2 : if ( m -> m_len < ETHER_HDR_LEN && ( m = m_pullup ( m , ETHER_HDR_LEN ) ) == NULL ) { printf ( " " " \n " ) ; break ; } ether_demux ( m -> m_pkthdr . rcvif , m ) ; break ; case DIR_OUT | PROTO_LAYER2 : ether_output_frame ( ifp , m ) ; break ; case DIR_DROP : FREE_PKT ( m ) ; break ; default : printf ( " \n " , dst ) ; FREE_PKT ( m ) ; break ; } } }
forward a chain of packets to the proper destination.
forward a chain of packets to the proper destination .
/* gcc 3.4.6 complains */ /* should not happen */ /* extract the dummynet info, rename the tag
			 * to carry reinject info.
			 */ /* DN_TO_IFB_FWD: */ /* DN_TO_ETH_DEMUX: */ /*
			 * The Ethernet code assumes the Ethernet header is
			 * contiguous in the first mbuf header.
			 * Insure this is true.
			 */ /* N_TO_ETH_OUT: */ /* drop the packet after some time */