- struct dn_pkt *pkt ;
-
- while ( (pkt = pipe->head) && DN_KEY_LEQ(pkt->output_time, curr_time) ) {
- /*
- * first unlink, then call procedures, since ip_input() can invoke
- * ip_output() and viceversa, thus causing nested calls
- */
- pipe->head = DN_NEXT(pkt) ;
-
- /*
- * The actual mbuf is preceded by a struct dn_pkt, resembling an mbuf
- * (NOT A REAL one, just a small block of malloc'ed memory) with
- * m_type = MT_DUMMYNET
- * m_next = actual mbuf to be processed by ip_input/output
- * m_data = the matching rule
- * and some other fields.
- * The block IS FREED HERE because it contains parameters passed
- * to the called routine.
- */
- switch (pkt->dn_dir) {
- case DN_TO_IP_OUT:
- (void)ip_output((struct mbuf *)pkt, NULL, NULL, 0, NULL);
- rt_unref (pkt->ro.ro_rt) ;
- break ;
-
- case DN_TO_IP_IN :
- ip_input((struct mbuf *)pkt) ;
- break ;
-
+ struct mbuf *m ;
+ struct dn_pkt_tag *pkt ;
+ struct ip *ip;
+
+ lck_mtx_assert(dn_mutex, LCK_MTX_ASSERT_OWNED);
+
+ while ( (m = pipe->head) ) {
+ pkt = dn_tag_get(m);
+ if ( !DN_KEY_LEQ(pkt->output_time, curr_time) )
+ break;
+ /*
+ * first unlink, then call procedures, since ip_input() can invoke
+ * ip_output() and viceversa, thus causing nested calls
+ */
+ pipe->head = m->m_nextpkt ;
+ m->m_nextpkt = NULL;
+
+ /* XXX: drop the lock for now to avoid LOR's */
+ lck_mtx_unlock(dn_mutex);
+ switch (pkt->dn_dir) {
+ case DN_TO_IP_OUT: {
+ struct route tmp_rt = pkt->ro;
+ (void)ip_output(m, NULL, NULL, pkt->flags, NULL);
+ if (tmp_rt.ro_rt) {
+ rtfree(tmp_rt.ro_rt);
+ }
+ break ;
+ }
+ case DN_TO_IP_IN :
+ ip = mtod(m, struct ip *);
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+ proto_inject(PF_INET, m);
+ break ;
+