-/* uipc_syscalls.c 4.26 82/09/06 */
+/* uipc_syscalls.c 4.39 82/12/28 */
#include "../h/param.h"
#include "../h/systm.h"
#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"
-socket()
-{
-
-}
-
-bind()
-{
-
-}
-
-listen()
-{
-
-}
-
-accept()
-{
-
-}
-
-connect()
-{
-
-}
-
-socketpair()
-{
-
-}
-
-sendto()
-{
-
-}
-
-send()
-{
-
-}
-
-recvfrom()
-{
-
-}
-
-recv()
-{
-
-}
-
-sendmsg()
-{
-
-}
-
-recvmsg()
-{
-
-}
-
-shutdown()
-{
-
-}
-
/*
- * 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()
-{
- 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.
- */
-osocket()
+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.
- */
-oaccept()
+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) {
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;
}
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.
- */
-oconnect()
+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) {
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.
- */
-osend()
+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) {
}
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.
- */
-oreceive()
+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) {
}
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_READ) == 0) {
u.u_error = EFAULT;
return;
}
- u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 0, &auio);
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 = 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) {
+ 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;
+ }
+ 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;
+ 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);
}
/*
} *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)
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);
}