#include "sys/param.h" #include "sys/config.h" #include "sys/types.h" #include "sys/mmu.h" #include "sys/sysmacros.h" #include "sys/dir.h" #include "sys/proc.h" #include "sys/seg.h" #include "sys/signal.h" #include "sys/errno.h" #include "sys/user.h" #include "sys/systm.h" #include "sys/inode.h" #include "sys/ino.h" #include "sys/file.h" #include "sys/conf.h" #include "net/misc.h" #include "net/protosw.h" #include "net/socket.h" #include "net/socketvar.h" #include "net/ubavar.h" #include "sys/map.h" #include "sys/callo.h" #include "net/if.h" #include "net/in.h" #include "net/in_systm.h" #include "net/ip.h" #include "net/ip_var.h" #include "sys/var.h" /* * SCCS id @(#)syslocal.c 1.6 (Berkeley) 2/27/82 */ /* * These routines implement local system calls */ short netoff = 0; int protoslow; int protofast; int ifnetslow; int nselcoll; char netstak[3000]; /* stack when system is "in the network" (mch.s) */ char * svstak; /* globle where mch.s saves current stack */ /* * Initialize network code. Called from main(). */ netinit() { extern struct uba_device ubdinit[]; register struct uba_driver *udp; register struct uba_device *ui = &ubdinit[0]; if(netoff) return; mbinit(); for(ui = &ubdinit[0] ; udp = ui->ui_driver ; ui++) { /* ud_probe could go here */ ui->ui_alive = 1; udp->ud_dinfo[ui->ui_unit] = ui; (*udp->ud_attach)(ui); } #ifdef INET loattach(); /* XXX */ ifinit(); pfinit(); /* must follow interfaces */ #endif #ifdef TCPACKMOST /* * Fool some systems into thinking that tcp_maxseg == sbspace == * max window. Ergo, force acking of most packets when talking to * (the vax) */ { extern int tcp_sendspace, tcp_recvspace; tcp_sendspace = tcp_recvspace = 1024; } #endif } /* netreset -- network reset system call */ /* 3/23/83 billn: doesnt quite work yet */ netreset() { register wait = 100000; register s = spl6(); register struct file *fp; extern int netisr; netoff = 1; /* prevent net traffic (during resets) */ netisr = 0; /* unbeknownst sockets to UNIX */ for (fp = &file[0]; fp < (struct file *)v.ve_file; fp++) { if ((fp->f_flag & FSOCKET) && fp->f_count) { bzero ((char *)fp, sizeof (struct file)); } } mbinit(); /* relink mbufs */ #ifdef INET ifinit(); /* re-init interfaces */ pfinit(); /* must follow interfaces */ #endif splx(s); while (wait--); /* wait for pending ints. */ netoff = 0; /* allow traffic */ } splimp() { return spl6(); } splnet() { return spl6(); } /* * Entered via software interrupt vector at spl1. Check netisr bit array * for tasks requesting service. */ netintr() { register int onetisr; while(spl7(),(onetisr = netisr)) { netisr = 0; (void) splnet(); if (onetisr & (1<nfd > NOFILE) ap->nfd = NOFILE; if (ap->nfd < 0) { u.u_error = EBADF; return; } if (ap->rp && copyin((caddr_t)ap->rp,(caddr_t)&rd,sizeof(fd_set))) return; if (ap->wp && copyin((caddr_t)ap->wp,(caddr_t)&wr,sizeof(fd_set))) return; retry: ncoll = nselcoll; u.u_procp->p_flag |= SSEL; if (ap->rp) readable = selscan(ap->nfd, rd, &nfds, FREAD); if (ap->wp) writeable = selscan(ap->nfd, wr, &nfds, FWRITE); if (u.u_error) goto done; if (readable || writeable) goto done; rem = (ap->timo+999)/1000 - (time - t); if (ap->timo == 0 || rem <= 0) goto done; s = spl6(); if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { u.u_procp->p_flag &= ~SSEL; splx(s); goto retry; } u.u_procp->p_flag &= ~SSEL; if (rem) { bcopy((caddr_t)u.u_qsav, (caddr_t)lqsav, sizeof (label_t)); if (save(u.u_qsav)) { rm_callout(setrun, (caddr_t)u.u_procp); u.u_error = EINTR; splx(s); goto done; } rem = rem*v.v_hz; timeout(setrun, (caddr_t)u.u_procp, rem); } sleep((caddr_t)&selwait, PZERO+1); if (rem) { bcopy((caddr_t)lqsav, (caddr_t)u.u_qsav, sizeof (label_t)); rm_callout(setrun, (caddr_t)u.u_procp); } splx(s); goto retry; done: rd.fds_bits[0] = readable; wr.fds_bits[0] = writeable; u.u_rval1 = nfds; if (ap->rp) (void) copyout((caddr_t)&rd, (caddr_t)ap->rp, sizeof(fd_set)); if (ap->wp) (void) copyout((caddr_t)&wr, (caddr_t)ap->wp, sizeof(fd_set)); } /* * remove entry in callout vector * which is scanned by clock interrupt */ rm_callout(func,arg) int (*func)(); caddr_t arg; { register struct callo *p1, *p2; register int tt; int pri; p1 = &callout[0]; pri = spl7(); while(p1->c_func != 0) { if ((p1->c_func == func) && (p1->c_arg == arg)) break; p1++; } if (p1 >= (struct callo *)v.ve_call-1) { printf("Timeout entry not found, not deleted\n"); return; } /* copy everything that follows in the list up one position, adding our unused time to theirs */ tt = p1->c_time; p2 = p1; while(p1->c_func != 0) { p2++; p1->c_time = p2->c_time + tt; p1->c_func = p2->c_func; p1->c_arg = p2->c_arg; p1 = p2; } splx(pri); } long selscan(nfd, fds, nfdp, flag) int nfd; fd_set fds; int *nfdp, flag; { struct file *fp; struct inode *ip; long bits,res = 0; int i, able; bits = fds.fds_bits[0]; while (i = ffs(bits)) { if (i >= nfd) break; bits &= ~(1L<<(i-1)); fp = u.u_ofile[i-1]; if (fp == NULL) { u.u_error = EBADF; return (0); } if (fp->f_flag & FSOCKET) able = soselect((struct socket *)fp->f_socket, flag); else { ip = fp->f_inode; switch (ip->i_mode & IFMT) { case IFCHR: #ifdef notdef able = (*cdevsw[major(ip->i_rdev)].d_select) ((int)ip->i_rdev, flag); #else /* * for now the only char device we need * to select on is the control side of * ptys -- for the rlogin deamon. At * some point someone can put general * select code into all char. devices. */ { extern int ptc_dev; if (major((int)(ip->i_rdev)) == ptc_dev) able = ptcselect((int)ip->i_rdev, flag); else able = 0; } #endif break; case IFIFO: case IFBLK: case IFREG: case IFDIR: able = 1; break; } } if (able) { res |= (1L<<(i-1)); (*nfdp)++; } } return (res); } ffs(mask) long mask; { register int i; register imask; if (mask == 0) return (0); imask = loint(mask); for(i=1; i<=16; i++) { if (imask & 1) return (i); imask >>= 1; } imask = hiint(mask); for(; i<=32; i++) { if (imask & 1) return (i); imask >>= 1; } return (0); /* can't get here anyway! */ } #ifdef notdef /*ARGSUSED*/ seltrue(dev, flag) dev_t dev; int flag; { return (1); } #endif selwakeup(p, coll) register struct proc *p; int coll; { int s; if (coll) { nselcoll++; wakeup((caddr_t)&selwait); } s = spl6(); if (p) { if (p->p_wchan == (caddr_t)&selwait) setrun(p); else { if (p->p_flag & SSEL) p->p_flag &= ~SSEL; } } splx(s); } #ifdef notdef /* ARGSUSED */ nulselect(x, y) { return 0; } #endif char hostname[32] = "hostnameunknown"; int hostnamelen = 16; gethostname() { register struct a { char *hostname; int len; } *uap = (struct a *)u.u_ap; register int len; len = uap->len; if (len > hostnamelen) len = hostnamelen; if (copyout((caddr_t)hostname, (caddr_t)uap->hostname, len)) u.u_error = EFAULT; } sethostname() { register struct a { char *hostname; int len; } *uap = (struct a *)u.u_ap; if (!suser()) return; if (uap->len > sizeof (hostname) - 1) { u.u_error = EINVAL; return; } hostnamelen = uap->len; if (copyin((caddr_t)uap->hostname, hostname, uap->len + 1)) u.u_error = EFAULT; } /* * Some misc. subroutines. Prob should be in a sep module */ #ifdef notdef /* system 3 has it's own */ /* * Provide about n microseconds of delay */ delay(n) long n; { register hi,low; low = (n&0177777); hi = n>>16; if(hi==0) hi=1; do { do { } while(--low); } while(--hi); } #endif /* * compare bytes; same result as VAX cmpc3. */ bcmp(s1, s2, n) register char *s1, *s2; register n; { do if(*s1++ != *s2++) break; while(--n); return(n); } /* * Insert an entry onto queue. */ _insque(e,prev) register struct vaxque *e,*prev; { register x = spl7(); e->vq_prev = prev; e->vq_next = prev->vq_next; if (prev->vq_next) prev->vq_next->vq_prev = e; prev->vq_next = e; splx(x); } /* * Remove an entry from queue. */ _remque(e) register struct vaxque *e; { register x = spl7(); e->vq_prev->vq_next = e->vq_next; if (e->vq_next) e->vq_next->vq_prev = e->vq_prev; splx(x); } struct proc * pfind(pid) int pid; { register struct proc *p; for (p=proc; p < &proc[v.v_proc]; p++) if (p->p_pid == pid) return (p); return ((struct proc *)0); } /* bzero(p,n) -- zero n bytes starting at p */ bzero(p,n) register char * p; register n; { if (n) do { *p++ = 0; } while (--n); } /* * iomalloc -- allocate clks of mem. for io. * Right now, no dma. */ mbioalloc() { return 0; } /* * mballoc should be combined with/done like memap(). THIS STUFF DEPENDS * ON MSIZE BEING A POWER OF 2. */ #define MBUFCONFIG 1 /* undef extern of Mbuf, mbuf */ #include char mbufbufs[(NMBUFS+1)*MSIZE]; struct mbuf * mballoc() { unsigned int location = (unsigned int)(&mbufbufs[0]); int slop = location & (MSIZE-1); /* round actual buffers to MSIZE boundry */ return ((struct mbuf*)(location + MSIZE - slop)); }