X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/d3d550b587da16d1f4dd274bf25e584b09ff6b4e..127f7d76e6fc650e9450bf325ab8231bb31f61ec:/usr/src/sys/kern/uipc_syscalls.c diff --git a/usr/src/sys/kern/uipc_syscalls.c b/usr/src/sys/kern/uipc_syscalls.c index b5d49314b1..3d83c4b2c8 100644 --- a/usr/src/sys/kern/uipc_syscalls.c +++ b/usr/src/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* uipc_syscalls.c 4.24 82/08/22 */ +/* uipc_syscalls.c 4.39 82/12/28 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,223 +12,145 @@ #include "../h/protosw.h" #include "../h/socket.h" #include "../h/socketvar.h" -#include "../net/in.h" -#include "../net/in_systm.h" #include "../h/descrip.h" #include "../h/uio.h" -ssocreate() -/*###21 [lint] ssocreate defined( sys_socket.c(21) ), but never used%%%*/ -{ - -} - -ssobind() -/*###26 [lint] ssobind defined( sys_socket.c(26) ), but never used%%%*/ -{ - -} - -ssolisten() -/*###31 [lint] ssolisten defined( sys_socket.c(31) ), but never used%%%*/ -{ - -} - -ssoaccept() -/*###36 [lint] ssoaccept defined( sys_socket.c(36) ), but never used%%%*/ -{ - -} - -ssoconnect() -/*###41 [lint] ssoconnect defined( sys_socket.c(41) ), but never used%%%*/ -{ - -} - -ssocreatepair() -/*###46 [lint] ssocreatepair defined( sys_socket.c(46) ), but never used%%%*/ -{ - -} - -ssosendto() -/*###51 [lint] ssosendto defined( sys_socket.c(51) ), but never used%%%*/ -{ - -} - -ssosend() -/*###56 [lint] ssosend defined( sys_socket.c(56) ), but never used%%%*/ -{ - -} - -ssorecvfrom() -/*###61 [lint] ssorecvfrom defined( sys_socket.c(61) ), but never used%%%*/ -{ - -} - -ssorecv() -/*###66 [lint] ssorecv defined( sys_socket.c(66) ), but never used%%%*/ -{ - -} - -ssosendm() -/*###71 [lint] ssosendm defined( sys_socket.c(71) ), but never used%%%*/ -{ - -} - -ssorecvm() -/*###76 [lint] ssorecvm defined( sys_socket.c(76) ), but never used%%%*/ -{ - -} - -ssoshutdown() -/*###81 [lint] ssoshutdown defined( sys_socket.c(81) ), but never used%%%*/ -{ - -} - /* - * Socket system call interface. - * - * These routines interface the socket routines to UNIX, - * isolating the system interface from the socket-protocol interface. - * - * TODO: - * SO_INTNOTIFY + * System call interface to the socket abstraction. */ -static struct sockproto localproto = { PF_UNIX, 0 }; -/* - * Pipe system call interface. - */ -spipe() -{ - register struct file *rf, *wf; - struct socket *rso, *wso; - int r; - - u.u_error = socreate(&rso, SOCK_STREAM, - &localproto, (struct sockaddr *)0, 0); - if (u.u_error) - return; - u.u_error = socreate(&wso, SOCK_STREAM, - &localproto, (struct sockaddr *)0, 0); - if (u.u_error) - goto free; - rf = falloc(); - if (rf == NULL) - goto free2; - r = u.u_r.r_val1; - rf->f_flag = FREAD; - rf->f_type = DTYPE_SOCKET; - rf->f_socket = rso; - wf = falloc(); - if (wf == NULL) - goto free3; - wf->f_flag = FWRITE; - wf->f_type = DTYPE_SOCKET; - wf->f_socket = wso; - u.u_r.r_val2 = u.u_r.r_val1; - u.u_r.r_val1 = r; - if (piconnect(wso, rso) == 0) - goto free4; - return; -free4: - wf->f_count = 0; - u.u_ofile[u.u_r.r_val2] = 0; -free3: - rf->f_count = 0; - u.u_ofile[r] = 0; -free2: - wso->so_state |= SS_NOFDREF; - sofree(wso); -free: - rso->so_state |= SS_NOFDREF; - sofree(rso); -} - -/* - * Socket system call interface. Copy sa arguments - * set up file descriptor and call internal socket - * creation routine. - */ -ssocket() +socket() { register struct a { + int domain; int type; - struct sockproto *asp; - struct sockaddr *asa; - int options; + int protocol; + struct socketopt *opt; } *uap = (struct a *)u.u_ap; - struct sockproto sp; - struct sockaddr sa; struct socket *so; register struct file *fp; + struct socketopt aopt; - if ((fp = falloc()) == NULL) + u.u_error = sockopt(&aopt, (caddr_t)uap->opt); + if (u.u_error) return; + if ((fp = falloc()) == NULL) + goto freeopt; fp->f_flag = FREAD|FWRITE; fp->f_type = DTYPE_SOCKET; - if (uap->asp && copyin((caddr_t)uap->asp, (caddr_t)&sp, sizeof (sp)) || - uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { - u.u_error = EFAULT; - goto bad; - } - u.u_error = socreate(&so, uap->type, - uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options); + u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol, &aopt); if (u.u_error) goto bad; fp->f_socket = so; +freeopt: + if (uap->opt) + (void) m_free(dtom(aopt.so_optdata)); return; bad: u.u_ofile[u.u_r.r_val1] = 0; fp->f_count = 0; + goto freeopt; } -/* - * Accept system call interface. - */ -saccept() +bind() { register struct a { - int fdes; - struct sockaddr *asa; + int s; + caddr_t name; + int namelen; + struct socketopt *opt; } *uap = (struct a *)u.u_ap; - struct sockaddr sa; register struct file *fp; - struct socket *so; - int s; + struct mbuf *nam; + struct socketopt aopt; - if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) { - u.u_error = EFAULT; + fp = getf(uap->s); + if (fp == 0) + return; + if (fp->f_type != DTYPE_SOCKET) { + u.u_error = ENOTSOCK; return; } - fp = getf(uap->fdes); + u.u_error = sockname(&nam, uap->name, uap->namelen); + if (u.u_error) + return; + u.u_error = sockopt(&aopt, (caddr_t)uap->opt); + if (u.u_error) { + m_freem(nam); + goto freeopt; + } + u.u_error = sobind(fp->f_socket, nam, &aopt); + m_freem(nam); +freeopt: + if (uap->opt) + (void) m_free(dtom(aopt.so_optdata)); +} + +listen() +{ + register struct a { + int s; + int backlog; + } *uap = (struct a *)u.u_ap; + register struct file *fp; + + fp = getf(uap->s); if (fp == 0) return; if (fp->f_type != DTYPE_SOCKET) { u.u_error = ENOTSOCK; return; } + u.u_error = solisten(fp->f_socket, uap->backlog); +} + +accept() +{ + register struct a { + int s; + caddr_t name; + int *anamelen; + struct socketopt *opt; + } *uap = (struct a *)u.u_ap; + register struct file *fp; + struct mbuf *nam; + struct socketopt aopt; + int namelen; + int s; + register struct socket *so; + + if (uap->name == 0) + goto noname; + u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen, + sizeof (namelen)); + if (u.u_error) + return; + if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) { + u.u_error = EFAULT; + return; + } +noname: + u.u_error = sockopt(&aopt, (caddr_t)uap->opt); + if (u.u_error) + return; + fp = getf(uap->s); + if (fp == 0) + goto bad; + if (fp->f_type != DTYPE_SOCKET) { + u.u_error = ENOTSOCK; + goto bad; + } s = splnet(); so = fp->f_socket; if ((so->so_options & SO_ACCEPTCONN) == 0) { u.u_error = EINVAL; splx(s); - return; + goto bad; } if ((so->so_state & SS_NBIO) && so->so_qlen == 0) { u.u_error = EWOULDBLOCK; splx(s); - return; + goto bad; } while (so->so_qlen == 0 && so->so_error == 0) { if (so->so_state & SS_CANTRCVMORE) { @@ -240,12 +162,12 @@ saccept() if (so->so_error) { u.u_error = so->so_error; splx(s); - return; + goto bad; } if ((so->so_options & SO_NEWFDONCONN) == 0) { struct socket *nso = so->so_q; (void) soqremque(nso, 1); - soclose(so, 1); + u.u_error = soclose(so, 1); fp->f_socket = nso; nso->so_q = 0; so = nso; @@ -253,46 +175,56 @@ saccept() } if (ufalloc() < 0) { splx(s); - return; + goto bad; } fp = falloc(); if (fp == 0) { u.u_ofile[u.u_r.r_val1] = 0; splx(s); - return; + goto bad; + } + { struct socket *aso = so->so_q; + if (soqremque(aso, 1) == 0) + panic("accept"); + so = aso; } fp->f_type = DTYPE_SOCKET; fp->f_flag = FREAD|FWRITE; - fp->f_socket = so->so_q; - so->so_q = so->so_q->so_q; - so->so_qlen--; + fp->f_socket = so; ret: - soaccept(so, &sa); - if (uap->asa) - (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); + nam = m_get(M_WAIT, MT_SONAME); + (void) soaccept(so, nam, &aopt); + if (uap->name) { + if (namelen > nam->m_len) + namelen = nam->m_len; + /* SHOULD COPY OUT A CHAIN HERE */ + (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name, + (u_int)namelen); + (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen, + sizeof (*uap->anamelen)); + } + m_freem(nam); splx(s); +bad: + if (uap->opt) + (void) m_free(dtom(aopt.so_optdata)); } -/* - * Connect socket to foreign peer; system call - * interface. Copy sa arguments and call internal routine. - */ -sconnect() +connect() { register struct a { - int fdes; - struct sockaddr *a; + int s; + caddr_t name; + int namelen; + struct socketopt *opt; } *uap = (struct a *)u.u_ap; - struct sockaddr sa; register struct file *fp; register struct socket *so; + struct mbuf *nam; + struct socketopt aopt; int s; - if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) { - u.u_error = EFAULT; - return; - } - fp = getf(uap->fdes); + fp = getf(uap->s); if (fp == 0) return; if (fp->f_type != DTYPE_SOCKET) { @@ -300,40 +232,58 @@ sconnect() return; } so = fp->f_socket; - u.u_error = soconnect(so, &sa); + u.u_error = sockname(&nam, uap->name, uap->namelen); if (u.u_error) return; + u.u_error = sockopt(&aopt, (caddr_t)uap->opt); + if (u.u_error) { + m_freem(nam); + return; + } + u.u_error = soconnect(so, nam, &aopt); + if (u.u_error) + goto bad; s = splnet(); if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { u.u_error = EINPROGRESS; splx(s); - return; + goto bad; } while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) sleep((caddr_t)&so->so_timeo, PZERO+1); u.u_error = so->so_error; so->so_error = 0; splx(s); +bad: + m_freem(nam); + if (uap->opt) + (void) m_free(dtom(aopt.so_optdata)); + return; } -/* - * Send data on socket. - */ -ssend() +socketpair() +{ + + u.u_error = ENOENT; +} + +sendto() { register struct a { - int fdes; - struct sockaddr *asa; - caddr_t cbuf; - unsigned count; + int s; + caddr_t buf; + int len; + int flags; + caddr_t to; + int tolen; } *uap = (struct a *)u.u_ap; register struct file *fp; - struct sockaddr sa; struct uio auio; struct iovec aiov; + struct mbuf *to; - fp = getf(uap->fdes); + fp = getf(uap->s); if (fp == 0) return; if (fp->f_type != DTYPE_SOCKET) { @@ -342,37 +292,136 @@ ssend() } auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - aiov.iov_base = uap->cbuf; - aiov.iov_len = uap->count; - auio.uio_resid = uap->count; + aiov.iov_base = uap->buf; + aiov.iov_len = uap->len; + auio.uio_resid = uap->len; auio.uio_segflg = 0; auio.uio_offset = 0; /* XXX */ - if (useracc(uap->cbuf, uap->count, B_READ) == 0 || - uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { + if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { u.u_error = EFAULT; return; } - u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0, &auio); - u.u_r.r_val1 = uap->count - auio.uio_resid; + u.u_error = sockname(&to, uap->to, uap->tolen); + if (u.u_error) + goto bad; + u.u_error = sosend(fp->f_socket, to, &auio, uap->flags); + u.u_r.r_val1 = uap->len - auio.uio_resid; +bad: + m_freem(to); } -/* - * Receive data on socket. - */ -sreceive() +send() { register struct a { - int fdes; - struct sockaddr *asa; - caddr_t cbuf; - u_int count; + int s; + caddr_t buf; + int len; + int flags; } *uap = (struct a *)u.u_ap; register struct file *fp; - struct sockaddr sa; struct uio auio; struct iovec aiov; - fp = getf(uap->fdes); + fp = getf(uap->s); + if (fp == 0) + return; + if (fp->f_type != DTYPE_SOCKET) { + u.u_error = ENOTSOCK; + return; + } + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = uap->buf; + aiov.iov_len = uap->len; + auio.uio_resid = uap->len; + auio.uio_segflg = 0; + auio.uio_offset = 0; /* XXX */ + if (useracc(uap->buf, (u_int)uap->len, B_READ) == 0) { + u.u_error = EFAULT; + return; + } + if (u.u_error) + return; + u.u_error = sosend(fp->f_socket, (struct mbuf *)0, &auio, uap->flags); + u.u_r.r_val1 = uap->len - auio.uio_resid; +} + +recvfrom() +{ + register struct a { + int s; + caddr_t buf; + int len; + int flags; + caddr_t from; + int *fromlenaddr; + } *uap = (struct a *)u.u_ap; + register struct file *fp; + struct uio auio; + struct iovec aiov; + struct mbuf *from; + int fromlen; + + u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&fromlen, + sizeof (fromlen)); + if (u.u_error) + return; + fp = getf(uap->s); + if (fp == 0) + return; + if (fp->f_type != DTYPE_SOCKET) { + u.u_error = ENOTSOCK; + return; + } + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + aiov.iov_base = uap->buf; + aiov.iov_len = uap->len; + auio.uio_resid = uap->len; + auio.uio_segflg = 0; + auio.uio_offset = 0; /* XXX */ + if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { + u.u_error = EFAULT; + return; + } + from = 0; + u.u_error = soreceive(fp->f_socket, &from, &auio, uap->flags); + if (u.u_error) + goto bad; + if (from == 0) + fromlen = 0; + else { + if (fromlen > from->m_len) + fromlen = from->m_len; + u.u_error = copyout(mtod(from, caddr_t), uap->from, + (u_int)fromlen); + if (u.u_error) + goto bad; + } + u.u_error = copyout((caddr_t)&fromlen, (caddr_t)uap->fromlenaddr, + sizeof (fromlen)); + if (u.u_error) + goto bad; + u.u_r.r_val1 = uap->len - auio.uio_resid; +bad: + if (from) + m_freem(from); + return; +} + +recv() +{ + register struct a { + int s; + caddr_t buf; + int len; + int flags; + } *uap = (struct a *)u.u_ap; + register struct file *fp; + struct uio auio; + struct iovec aiov; + + fp = getf(uap->s); if (fp == 0) return; if (fp->f_type != DTYPE_SOCKET) { @@ -381,22 +430,82 @@ sreceive() } auio.uio_iov = &aiov; auio.uio_iovcnt = 1; - aiov.iov_base = uap->cbuf; - aiov.iov_len = uap->count; - auio.uio_resid = uap->count; + aiov.iov_base = uap->buf; + aiov.iov_len = uap->len; + auio.uio_resid = uap->len; auio.uio_segflg = 0; auio.uio_offset = 0; /* XXX */ - if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 || - uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) { + if (useracc(uap->buf, (u_int)uap->len, B_WRITE) == 0) { u.u_error = EFAULT; return; } - u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0, &auio); + u.u_error = + soreceive(fp->f_socket, (struct mbuf **)0, &auio, uap->flags); + u.u_r.r_val1 = uap->len - auio.uio_resid; +} + +sendmsg() +{ + + u.u_error = EINVAL; +} + +recvmsg() +{ + + u.u_error = EINVAL; +} + +shutdown() +{ + + u.u_error = EINVAL; +} + +pipe() +{ + register struct file *rf, *wf; + struct socket *rso, *wso; + int r; + + u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0, + (struct socketopt *)0); if (u.u_error) return; - if (uap->asa) - (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa)); - u.u_r.r_val1 = uap->count - auio.uio_resid; + u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0, + (struct socketopt *)0); + if (u.u_error) + goto free; + rf = falloc(); + if (rf == NULL) + goto free2; + r = u.u_r.r_val1; + rf->f_flag = FREAD; + rf->f_type = DTYPE_SOCKET; + rf->f_socket = rso; + wf = falloc(); + if (wf == NULL) + goto free3; + wf->f_flag = FWRITE; + wf->f_type = DTYPE_SOCKET; + wf->f_socket = wso; + u.u_r.r_val2 = u.u_r.r_val1; + u.u_r.r_val1 = r; + if (piconnect(wso, rso) == 0) + goto free4; + return; +free4: + wf->f_count = 0; + u.u_ofile[u.u_r.r_val2] = 0; +free3: + rf->f_count = 0; + u.u_ofile[r] = 0; +free2: + wso->so_state |= SS_NOFDREF; + sofree(wso); +free: + rso->so_state |= SS_NOFDREF; + sofree(rso); } /* @@ -410,7 +519,7 @@ ssocketaddr() } *uap = (struct a *)u.u_ap; register struct file *fp; register struct socket *so; - struct sockaddr addr; + struct mbuf *m; fp = getf(uap->fdes); if (fp == 0) @@ -420,10 +529,61 @@ ssocketaddr() return; } so = fp->f_socket; + m = m_getclr(M_WAIT, MT_SONAME); u.u_error = - (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr); + (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0); if (u.u_error) - return; - if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr))) - u.u_error = EFAULT; + goto bad; + u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, + sizeof (struct sockaddr)); +bad: + m_freem(m); +} + +sockname(aname, name, namelen) + struct mbuf **aname; + caddr_t name; + int namelen; +{ + register struct mbuf *m; + int error; + + if (namelen > MLEN) + return (EINVAL); + m = m_get(M_WAIT, MT_SONAME); + m->m_len = namelen; + error = copyin(name, mtod(m, caddr_t), (u_int)namelen); + if (error) + (void) m_free(m); + else + *aname = m; + return (error); +} + +sockopt(so, opt) + register struct socketopt *so; + caddr_t opt; +{ + register struct mbuf *m; + int error; + + if (opt == 0) { + so->so_optlen = 0; + so->so_optdata = 0; + return (0); + } + error = copyin((caddr_t)opt, (caddr_t)so, sizeof (struct socketopt)); + if (error) + return (error); + if (so->so_optlen < 0 || so->so_optlen > MLEN) + return (EINVAL); + m = m_get(M_WAIT, MT_SOOPTS); + m->m_len = so->so_optlen; + error = copyin(so->so_optdata, mtod(m, caddr_t), (u_int)m->m_len); + if (error) { + (void) m_free(m); + return (error); + } + so->so_optdata = mtod(m, caddr_t); + return (0); }