Index: ipx_input.c =================================================================== --- ipx_input.c (revision 194549) +++ ipx_input.c (working copy) @@ -1,7 +1,7 @@ /*- * Copyright (c) 1984, 1985, 1986, 1987, 1993 * The Regents of the University of California. - * Copyright (c) 2004-2005 Robert N. M. Watson + * Copyright (c) 2004-2009 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -104,6 +104,7 @@ static void ipx_undo_route(struct route *ro); static void ipx_forward(struct mbuf *m); static void ipxintr(struct mbuf *m); +static void ipx_watch_intr(struct mbuf *m); const union ipx_net ipx_zeronet; const union ipx_host ipx_zerohost; @@ -131,6 +132,13 @@ .nh_policy = NETISR_POLICY_SOURCE, }; +static struct netisr_handler ipx_watch_nh = { + .nh_name = "ipx_watch", + .nh_handler = ipx_watch_intr, + .nh_proto = NETISR_IPXWATCH, + .nh_policy = NETISR_POLICY_SOURCE, +}; + long ipx_pexseq; /* Locked with ipxpcb_list_mtx. */ /* @@ -156,6 +164,7 @@ ipx_hostmask.sipx_addr.x_host = ipx_broadhost; netisr_register(&ipx_nh); + netisr_register(&ipx_watch_nh); } /* @@ -453,17 +462,22 @@ } } -/* - * XXXRW: This code should be run in its own netisr dispatch to avoid a call - * back into the socket code from the IPX output path. - */ -void -ipx_watch_output(struct mbuf *m, struct ifnet *ifp) +static void +ipx_watch_intr(struct mbuf *m) { + struct ifnet *ifp; + struct m_tag *tag; struct ipxpcb *ipxp; struct ifaddr *ifa; struct ipx_ifaddr *ia; + tag = m_tag_find(m, PACKET_TAG_IPX_WATCH, NULL); + if (tag != NULL) { + ifp = (struct ifnet *)(tag + 1); + m_tag_delete(m, tag); + } else + ifp = NULL; + /* * Give any raw listeners a crack at the packet */ @@ -501,4 +515,26 @@ } } IPX_LIST_UNLOCK(); + m_freem(m); } + +void +ipx_watch_output(struct mbuf *m, struct ifnet *ifp) +{ + struct m_tag *tag; + + if (LIST_FIRST(&ipxrawpcb_list) == NULL) + return; + + m = m_copy(m, 0, (int)M_COPYALL); + if (m == NULL) + return; + if (ifp != NULL) { + tag = m_tag_get(PACKET_TAG_IPX_WATCH, sizeof(ifp), M_NOWAIT); + if (tag == NULL) { + m_freem(m); + return; + } + } + netisr_queue(NETISR_IPXWATCH, m); +}