/* * This may also be called for raw listeners. */ void idp_input(struct mbuf *m, ...) { struct nspcb *nsp; struct idp *idp = mtod(m, struct idp *); struct ifnet *ifp = m->m_pkthdr.rcvif; struct sockaddr_ns idp_ns; va_list ap; va_start(ap, m); nsp = va_arg(ap, struct nspcb *); va_end(ap); if (nsp == NULL) panic("No nspcb"); /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ bzero(&idp_ns, sizeof(idp_ns)); idp_ns.sns_len = sizeof(idp_ns); idp_ns.sns_family = AF_NS; idp_ns.sns_addr = idp->idp_sna; if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) { struct ifaddr *ifa; for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { if (ifa->ifa_addr->sa_family == AF_NS) { idp_ns.sns_addr.x_net = IA_SNS(ifa)->sns_addr.x_net; break; } } } nsp->nsp_rpt = idp->idp_pt; if ( ! (nsp->nsp_flags & NSP_RAWIN) ) { m->m_len -= sizeof (struct idp); m->m_pkthdr.len -= sizeof (struct idp); m->m_data += sizeof (struct idp); } if (sbappendaddr(&nsp->nsp_socket->so_rcv, snstosa(&idp_ns), m, (struct mbuf *)0) == 0) goto bad; sorwakeup(nsp->nsp_socket); return; bad: m_freem(m); }
nsintr() { register struct idp *idp; register struct mbuf *m; register struct nspcb *nsp; register int i; int len, s, error; char oddpacketp; next: /* * Get next datagram off input queue and get IDP header * in first mbuf. */ s = splimp(); IF_DEQUEUE(&nsintrq, m); splx(s); nsintr_getpck++; if (m == 0) return; if ((m->m_flags & M_EXT || m->m_len < sizeof (struct idp)) && (m = m_pullup(m, sizeof (struct idp))) == 0) { idpstat.idps_toosmall++; goto next; } /* * Give any raw listeners a crack at the packet */ for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) { struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL); if (m1) idp_input(m1, nsp); } idp = mtod(m, struct idp *); len = ntohs(idp->idp_len); if (oddpacketp = len & 1) { len++; /* If this packet is of odd length, preserve garbage byte for checksum */ } /* * Check that the amount of data in the buffers * is as at least much as the IDP header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ if (m->m_pkthdr.len < len) { idpstat.idps_tooshort++; goto bad; } if (m->m_pkthdr.len > len) { if (m->m_len == m->m_pkthdr.len) { m->m_len = len; m->m_pkthdr.len = len; } else m_adj(m, len - m->m_pkthdr.len); } if (idpcksum && ((i = idp->idp_sum)!=0xffff)) { idp->idp_sum = 0; if (i != (idp->idp_sum = ns_cksum(m, len))) { idpstat.idps_badsum++; idp->idp_sum = i; if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host)) error = NS_ERR_BADSUM; else error = NS_ERR_BADSUM_T; ns_error(m, error, 0); goto next; } } /* * Is this a directed broadcast? */ if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) { if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) && (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) && (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) && (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) { /* * Look to see if I need to eat this packet. * Algorithm is to forward all young packets * and prematurely age any packets which will * by physically broadcasted. * Any very old packets eaten without forwarding * would die anyway. * * Suggestion of Bill Nesheim, Cornell U. */ if (idp->idp_tc < NS_MAXHOPS) { idp_forward(m); goto next; } } /* * Is this our packet? If not, forward. */ } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) { idp_forward(m); goto next; } /* * Locate pcb for datagram. */ nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD); /* * Switch out to protocol's input routine. */ nsintr_swtch++; if (nsp) { if (oddpacketp) { m_adj(m, -1); } if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0) switch (idp->idp_pt) { case NSPROTO_SPP: spp_input(m, nsp); goto next; case NSPROTO_ERROR: ns_err_input(m); goto next; } idp_input(m, nsp); } else { ns_error(m, NS_ERR_NOSOCK, 0); } goto next; bad: m_freem(m); goto next; }