+ sp = &(mtod(m, struct raw_header *)->raw_protocol);
+ sa = &(mtod(m, struct raw_header *)->raw_address);
+
+ /*
+ * 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 (so->so_options & SO_DEBUG) {
+ printf("rawintr: sp=<%d,%d>, af=<%d,%x>\n",
+ sp->sp_family, sp->sp_protocol, sa->sa_family,
+ ((struct sockaddr_in *)sa)->sin_addr);
+ printf("pr=<%d,%d>\n", pr->pr_family, pr->pr_protocol);
+ }
+ if (pr->pr_family != sp->sp_family ||
+ pr->pr_protocol != sp->sp_protocol)
+ continue;
+ printf("rawintr: so=<%d,%x>\n", so->so_addr.sa_family,
+ ((struct sockaddr_in *)&so->so_addr)->sin_addr);
+ if (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.
+ */
+ 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, M_COPYALL))
+ goto nospace;
+ sbappend(&last->so_rcv, n);
+ sorwakeup(last);
+ }
+nospace:
+ last = so;
+ }
+ if (last == 0)
+ goto drop;
+ m = m_free(m); /* drop generic header */
+ sbappend(&last->so_rcv, m->m_next);
+ sorwakeup(last);
+ goto next;