/* * We only need open() and close() routines. open() calls socreate() * to allocate a "real" object behind the stream and mallocs some state * info for use by the svr4 emulator; close() deallocates the state * information and passes the underlying object to the normal socket close * routine. */ static int streamsopen(struct cdev *dev, int oflags, int devtype, struct thread *td) { struct filedesc *fdp; struct svr4_strm *st; struct socket *so; struct file *fp; int family, type, protocol; int error, fd; if (td->td_dupfd >= 0) return ENODEV; switch (dev2unit(dev)) { case dev_udp: family = AF_INET; type = SOCK_DGRAM; protocol = IPPROTO_UDP; break; case dev_tcp: family = AF_INET; type = SOCK_STREAM; protocol = IPPROTO_TCP; break; case dev_ip: case dev_rawip: family = AF_INET; type = SOCK_RAW; protocol = IPPROTO_IP; break; case dev_icmp: family = AF_INET; type = SOCK_RAW; protocol = IPPROTO_ICMP; break; case dev_unix_dgram: family = AF_LOCAL; type = SOCK_DGRAM; protocol = 0; break; case dev_unix_stream: case dev_unix_ord_stream: family = AF_LOCAL; type = SOCK_STREAM; protocol = 0; break; case dev_ptm: return svr4_ptm_alloc(td); default: return EOPNOTSUPP; } fdp = td->td_proc->p_fd; if ((error = falloc(td, &fp, &fd, 0)) != 0) return error; /* An extra reference on `fp' has been held for us by falloc(). */ error = socreate(family, &so, type, protocol, td->td_ucred, td); if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); return error; } finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, &svr4_netops); /* * Allocate a stream structure and attach it to this socket. * We don't bother locking so_emuldata for SVR4 stream sockets as * its value is constant for the lifetime of the stream once it * is initialized here. */ st = malloc(sizeof(struct svr4_strm), M_TEMP, M_WAITOK); st->s_family = so->so_proto->pr_domain->dom_family; st->s_cmd = ~0; st->s_afd = -1; st->s_eventmask = 0; so->so_emuldata = st; fdrop(fp, td); td->td_dupfd = fd; return ENXIO; }
/* * We only need open() and close() routines. open() calls socreate() * to allocate a "real" object behind the stream and mallocs some state * info for use by the svr4 emulator; close() deallocates the state * information and passes the underlying object to the normal socket close * routine. */ static int streamsopen(dev_t dev, int oflags, int devtype, struct thread *td) { int type, protocol; int fd; struct file *fp; struct socket *so; int error; int family; struct proc *p = td->td_proc; PROC_LOCK(p); if (td->td_dupfd >= 0) { PROC_UNLOCK(p); return ENODEV; } PROC_UNLOCK(p); switch (minor(dev)) { case dev_udp: family = AF_INET; type = SOCK_DGRAM; protocol = IPPROTO_UDP; break; case dev_tcp: family = AF_INET; type = SOCK_STREAM; protocol = IPPROTO_TCP; break; case dev_ip: case dev_rawip: family = AF_INET; type = SOCK_RAW; protocol = IPPROTO_IP; break; case dev_icmp: family = AF_INET; type = SOCK_RAW; protocol = IPPROTO_ICMP; break; case dev_unix_dgram: family = AF_LOCAL; type = SOCK_DGRAM; protocol = 0; break; case dev_unix_stream: case dev_unix_ord_stream: family = AF_LOCAL; type = SOCK_STREAM; protocol = 0; break; case dev_ptm: return svr4_ptm_alloc(td); default: return EOPNOTSUPP; } if ((error = falloc(td, &fp, &fd)) != 0) return error; if ((error = socreate(family, &so, type, protocol, td->td_ucred, td)) != 0) { FILEDESC_LOCK(p->p_fd); p->p_fd->fd_ofiles[fd] = 0; FILEDESC_UNLOCK(p->p_fd); ffree(fp); return error; } FILEDESC_LOCK(p->p_fd); fp->f_data = (caddr_t)so; fp->f_flag = FREAD|FWRITE; fp->f_ops = &svr4_netops; fp->f_type = DTYPE_SOCKET; FILEDESC_UNLOCK(p->p_fd); (void)svr4_stream_get(fp); PROC_LOCK(p); td->td_dupfd = fd; PROC_UNLOCK(p); return ENXIO; }