+ rawp = mtod(m, struct raw_header *);
+ sp = &rawp->raw_protocol;
+ sa = &rawp->raw_dst;
+
+ /*
+ * Find the appropriate socket(s) in which to place this
+ * packet. This is done by matching the protocol and
+ * address information prepended by raw_input against
+ * the info stored in the control block structures.
+ */
+ last = 0;
+ for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) {
+ so = rp->rcb_socket;
+ pr = so->so_proto;
+ if (pr->pr_family != sp->sp_family ||
+ (pr->pr_protocol && pr->pr_protocol != sp->sp_protocol))
+ continue;
+ if (so->so_addr.sa_family &&
+ sa->sa_family != so->so_addr.sa_family)
+ continue;
+ /*
+ * We assume the lower level routines have
+ * placed the address in a canonical format
+ * suitable for a structure comparison. Packets
+ * are duplicated for each receiving socket.
+ *
+ * SHOULD HAVE A NUMBER OF MECHANISMS FOR
+ * MATCHING BASED ON rcb_flags
+ */
+ if ((rp->rcb_flags & RAW_ADDR) &&
+ bcmp(sa->sa_data, so->so_addr.sa_data, 14) != 0)
+ continue;
+ /*
+ * To avoid extraneous packet copies, we keep
+ * track of the last socket the packet should be
+ * placed in, and make copies only after finding a
+ * socket which "collides".
+ */
+ if (last) {
+ struct mbuf *n;
+
+ if (n = m_copy(m->m_next, 0, (int)M_COPYALL))
+ goto nospace;
+ if (sbappendaddr(&last->so_rcv, &rawp->raw_src, n) == 0) {
+ /*
+ * Should drop notification of lost packet
+ * into this guy's queue, but...
+ */
+ m_freem(n);
+ goto nospace;
+ }
+ sorwakeup(last);
+ }
+nospace:
+ last = so;
+ }
+ if (last == 0)
+ goto drop;
+ if (sbappendaddr(&last->so_rcv, &rawp->raw_src, m->m_next) == 0)
+{
+printf("rawintr: sbappendaddr failed\n");
+ goto drop;
+}
+ (void) m_free(m); /* generic header */
+ sorwakeup(last);
+ goto next;