# #include "../h/param.h" #include "../h/conf.h" #include "../h/systm.h" #include "../h/user.h" #include "../h/userx.h" #include "../h/inode.h" #include "../h/file.h" #include "../h/reg.h" #include "../h/pkts.h" #include "../h/net.h" /* Net inode queue * Queue is modified by netopen, netclose, and ioctl; * it is not modified at interrupt time * Queue is searched at interrupt time as well * as non-interrupt time * Interlocking rule: lock out interrupts when * modify queue but not when search it */ struct que neti_que; netinit() { viiinit(); neti_que.q_head = NULL; neti_que.q_tail = NULL; neti_que.q_cnt = 0; netr_init(); inn_init(); } /* netopen nt_rte filled w. local net first hop dest. addr. if foreign host is specified in net connection and 1) foreign host is on my net/subnet or 2) foreign host is in host gate table */ netopen() { extern uchar; register struct inode *ip; register struct netino *nip; register struct netdf *netdp; int dev; int prot; int err; register struct file *fp; if ( (ip = namei(&uchar, 0)) == NULL) return; dev = ip->i_addr[0]; iput(ip); if (dev != netdev) { u.u_error = ENODEV; return; } netdp = u.u_arg[1]; prot = fuword(&netdp->n_prot1); if (prot != INETPROT) { u.u_error = EINVAL; return; } if ( (ip = ialloc(rootdev)) == NULL) return; ip->i_flag = IACC|IUPD; ip->i_mode = IALLOC|IFCHR|0666; ip->i_addr[0].d_major = dev.d_major & 0377; nip = ip; nip->nt_flags = NINTRUP; nip->nt_prot = fuword(&netdp->n_prot2); nip->nt_fhost.nt_shost[0] = fuword(&netdp->n_sfhost[0]); nip->nt_fhost.nt_shost[1] = fuword(&netdp->n_sfhost[1]); nip->nt_fskt = fuword(&netdp->n_fskt); nip->nt_lskt = fuword(&netdp->n_lskt); nip->nt_procp = u.u_procp; nip->nt_rte = net_rte(nip->nt_fhost.nt_lhost); if ((err = net_dchk(nip)) != 0) { u.u_error = err; iput(ip); return; } if ( (fp = falloc()) == NULL) { iput(ip); return; } fp->f_flag = FREAD|FWRITE; fp->f_inode = nip; spl6(); neti_enque(&neti_que, nip); spl0(); netr_start(); spl0(); #ifdef DEBUG show_niq(); #endif } /* net_dchk chk net definition * TCP protocol rules: * local socket must be specified * foreign host/socket must both be specified * or both be NULL * connection must be unique * Datagram protocol rules: * if local is NULL, foreign host/socket * must be NULL * if local socket is specified, * foreign host/socket must both be specified * or both be NULL * local socket must be unique * if foreign host/socket are specified, * pair must be unique * Otherwise * foreign host, foreign socket and local * socket must be NULL * connection must be unique */ net_dchk(nip) register struct netino *nip; { register int prot; register struct netino *nip2; prot = nip->nt_prot; switch(prot) { case TCPPROT: if ( (nip->nt_lskt == NULL) || ((nip->nt_fhost.nt_lhost == NULL) && (nip->nt_fskt != NULL)) || ((nip->nt_fhost.nt_lhost != NULL) && (nip->nt_fskt == NULL)) ) return(EINVAL); for (nip2 = neti_que.q_head; nip2 != NULL; nip2 = nip2->nt_forw) if ((prot == nip2->nt_prot) && (nip->nt_fhost.nt_lhost == nip2->nt_fhost.nt_lhost) && (nip->nt_fskt == nip2->nt_fskt) && (nip->nt_lskt == nip2->nt_lskt) ) return(EACCES); break; case DGPROT: if (nip->nt_lskt == NULL) { if ((nip->nt_fhost.nt_lhost != NULL) || (nip->nt_fskt != NULL) ) return(EINVAL); } else { if ( ((nip->nt_fhost.nt_lhost == NULL) && (nip->nt_fskt != NULL)) || ((nip->nt_fhost.nt_lhost != NULL) && (nip->nt_fskt == NULL)) ) return(EINVAL); } for (nip2 = neti_que.q_head; nip2 != NULL; nip2 = nip2->nt_forw) if ( (prot == nip2->nt_prot) && ((nip->nt_lskt == nip2->nt_lskt) || ( (nip->nt_fhost.nt_lhost != NULL) && (nip->nt_fhost.nt_lhost == nip2->nt_fhost.nt_lhost) && (nip->nt_fskt == nip2->nt_fskt) ) ) ) return(EACCES); break; default: if ( (nip->nt_fhost.nt_lhost != NULL) || (nip->nt_fskt != NULL) || (nip->nt_lskt != NULL) ) return(EINVAL); for (nip2 = neti_que.q_head; nip2 != NULL; nip2 = nip2->nt_forw) if (prot == nip2->nt_prot) return(EACCES); break; } return(0); } netclose(fp) register struct file *fp; { register struct netino *nip; nip = fp->f_inode; if (--fp->f_count > 0) { if ( (nip->nt_flags & NINTRUP) && (nip->nt_procp == u.u_procp) ) { nip->nt_flags &= (~NINTRUP); nip->nt_procp = NULL; } return; } spl6(); neti_deque(&neti_que, nip); neti_pdque(nip); spl0(); iput(nip); #ifdef DEBUG show_niq(); #endif if (neti_que.q_cnt == 0) { netwr_done(); netflush(); } return; } neti_enque(pque, nip) register struct que *pque; register struct netino *nip; { nip->nt_forw = NULL; nip->nt_back = pque->q_tail; if (pque->q_head == NULL) pque->q_head = nip; else pque->q_tail->nt_forw = nip; pque->q_tail = nip; pque->q_cnt++; } neti_deque(pque, nip) register struct que *pque; register struct netino *nip; { if (nip->nt_back == NULL) pque->q_head = nip->nt_forw; /* First on queue */ else nip->nt_back->nt_forw = nip->nt_forw; if (nip->nt_forw == NULL) pque->q_tail = nip->nt_back; /* Last on queue */ else nip->nt_forw->nt_back = nip->nt_back; pque->q_cnt--; } netu_err(ecode) short ecode; { u.u_error = ecode; } #ifdef DEBUG show_niq() { register struct netino *nip; printf("\nNeti_que\n"); for (nip = neti_que.q_head; nip != NULL; nip = nip->nt_forw) { printf("nip %o forw %o back %o dev %o flags %o procp %o\n", nip, nip->nt_forw, nip->nt_back, nip->nt_dev, nip->nt_flags, nip->nt_procp); printf(" prot %d lskt %d fhost %o %o fskt %d\n", nip->nt_prot, nip->nt_lskt, nip->nt_fhost.nt_shost[0], nip->nt_fhost.nt_shost[1], nip->nt_fskt); } } #endif