# #include "../h/param.h" #include "../h/user.h" #include "../h/userx.h" #include "../h/buf.h" #include "../h/inode.h" #include "../h/file.h" #include "../h/reg.h" #include "../h/pkts.h" #include "../h/net.h" extern viixmt(); /* Xmit i/o contol block * Interlock via B_BUSY bit * Interlocking done by physio(bio.c) and * viixint(vii.c) wh. calls iodone(bio.c); * If a strange error situation occurs, * netflush(vii.c) may unlock buffer */ struct buf xmtbuf; netwrite(dev) { struct pkt pkbuf; register struct pkt *uppkt, *ppkt; register short iphlen; struct netino *nip; /* addrok called by physio Assume for copyin and copyout that pkt is in user data space and that copyin/copyout will return(-1) if mem. fault encountered if (addrok()) return; */ uppkt = u.u_base; iphlen = (fubyte(&uppkt->pk_inet.ip_ihlver) & 017) << 2; if ((iphlen < IPHSIZ) || (iphlen > (IPHSIZ + IPOPTSZ)) ) return( netu_err(ENOSPC) ); if (copyin(&uppkt->pk_inet, &pkbuf.pk_inet, iphlen) == ERR) return( netu_err(EFAULT) ); ppkt = &pkbuf; if (mk_inet(&ppkt->pk_inet, u.u_count) == ERR) return( netu_err(ENOSPC) ); nip = (u.u_ofile[u.u_ar0[R0]])->f_inode; if (mk_net(ppkt, nip) == ERR) return( netu_err(EACCES) ); if (copyout(ppkt, uppkt, (NETHSIZ + IPHSIZ)) == ERR) return( netu_err(EFAULT) ); physio(&viixmt, &xmtbuf, dev, B_WRITE); } netwr_done() { if (xmtbuf.b_flags & B_BUSY) { neterrp("last net close and xmtbuf busy", neti_que.q_head, xmtbuf.b_flags, PROGERR); return(FALSE); } return(TRUE); } netread(dev) { register struct netino *nip; register struct rcvpkt *rp; struct buf rbuf; register struct buf *bp; short flag; nip = (u.u_ofile[u.u_ar0[R0]])->f_inode; spl6(); for (rp = rcvpktdir.rd_head; rp != NULL; rp = rp->rp_forw) if (rp->rp_inode == nip) break; if (rp == NULL) goto done; if (rp->rp_len > u.u_count) { u.u_error = ENOSPC; goto done; } rp->rp_flags |= N_LOCK; spl0(); bp = &rbuf; bp->b_addr = &rp->rp_net; iomove(bp, 0, rp->rp_len, B_READ); spl6(); flag = rp->rp_flags; if (u.u_error == 0) netp_deque(rp); else rp->rp_flags &= (~(N_LOCK|N_WANTED)); if (flag & N_WANTED) netr_start(); done: spl0(); return; } /* netrcnt Search rcv memory for first packet for net connection nip - return packet length */ netrcnt(nip) register struct netino *nip; { register struct rcvpkt *rp; register int nbyte; nbyte = 0; spl6(); for (rp = rcvpktdir.rd_head; rp != NULL; rp = rp->rp_forw) if (rp->rp_inode == nip) { nbyte = rp->rp_len; break; } spl0(); return(nbyte); }