-/* uipc_syscalls.c 4.2 81/11/14 */
+/* uipc_syscalls.c 4.18 82/06/12 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/inode.h"
#include "../h/buf.h"
#include "../h/mbuf.h"
-#include "../h/protocol.h"
#include "../h/protosw.h"
#include "../h/socket.h"
#include "../h/socketvar.h"
-#include "../h/inaddr.h"
-#include "../net/inet.h"
-#include "../net/inet_systm.h"
+#include "../net/in.h"
+#include "../net/in_systm.h"
/*
* Socket system call interface.
* isolating the system interface from the socket-protocol interface.
*
* TODO:
- * SO_NEWFDONCONN
* SO_INTNOTIFY
*/
-static struct in_addr localaddr = { PF_LOCAL };
+static struct sockproto localproto = { PF_UNIX, 0 };
/*
* Pipe system call interface.
*/
register struct file *rf, *wf;
struct socket *rso, *wso;
int r;
- struct in_addr waddr;
+COUNT(SPIPE);
- u.u_error = socket(&rso, SOCK_STREAM, &localaddr, SO_ACCEPTCONN);
+ u.u_error = socreate(&rso, SOCK_STREAM,
+ &localproto, (struct sockaddr *)0, 0);
if (u.u_error)
return;
- u.u_error = socket(&wso, SOCK_STREAM, &localaddr, 0);
+ u.u_error = socreate(&wso, SOCK_STREAM,
+ &localproto, (struct sockaddr *)0, 0);
if (u.u_error)
goto free;
rf = falloc();
wf->f_socket = wso;
u.u_r.r_val2 = u.u_r.r_val1;
u.u_r.r_val1 = r;
- if (pi_connect(rso, wso) == 0)
+ if (piconnect(wso, rso) == 0)
goto free4;
return;
free4:
rf->f_count = 0;
u.u_ofile[r] = 0;
free2:
+ wso->so_state |= SS_USERGONE;
sofree(wso);
free:
+ rso->so_state |= SS_USERGONE;
sofree(rso);
}
/*
- * Portal system call interface.
- *
- * This call creates a portal.
- * All the difficulty here is in dealing with errors.
- * A long sequence of steps is necessary:
- * 1. a socket must be allocated
- * 2. the server name length must be determined
- * 3. the portal must be entered into the file system
- * 4. the portal type and server must be entered into the portals' file
- * 5. a file descriptor referencing the socket+inode must be returned
- * If any errors occur in this process we must back it all out.
- */
-sportal()
-{
- register struct a {
- caddr_t name;
- int mode;
- caddr_t server;
- int kind;
- } *ap = (struct a *)u.u_ap;
- struct socket *so;
- struct inode *ip;
- struct file *fp;
- int err, len;
- char ch;
-
- /*
- * Allocate the socket for the portal.
- */
- u.u_error = socket(&so, SOCK_STREAM, &localaddr, SO_NEWFDONCONN);
- if (u.u_error)
- return;
-
- /*
- * Check that server name fis in a file system buffer.
- * This to simplify the creation of the portal service process.
- */
- if (ap->server) {
- u.u_dirp = ap->server;
- for (len = 0; len < BSIZE-2; len++) {
- register c = uchar();
- if (c < 0)
- goto bad;
- if (c == 0)
- break;
- }
- if (len == BSIZE - 2) {
- u.u_error = EINVAL;
- goto bad;
- }
- }
-
- /*
- * Make sure that nothing with the portal's name exists.
- */
- u.u_dirp = ap->name;
- ip = namei(uchar, 1);
- if (ip != NULL) {
- iput(ip);
- u.u_error = EEXIST;
- }
- if (u.u_error)
- goto bad;
-
- /*
- * Make a node in the file system for the portal.
- */
- ip = maknode((ap->mode & 0x7777) | IFPORTAL);
- if (ip == NULL)
- goto bad;
-
- /*
- * Make the first character of the contents of the
- * portal be the portal type and the rest of the portal be
- * the pathname of the server (if one was given).
- */
- ch = (char)ap->kind;
- u.u_base = (caddr_t)&ch;
- u.u_count = 1;
- u.u_offset = 0;
- u.u_segflg = 1;
- writei(ip);
- if (ap->server) {
- u.u_base = ap->server;
- u.u_count = len;
- u.u_segflg = 0;
- writei(ip);
- }
- if (u.u_error)
- goto bad2;
-
- /*
- * Allocate a file descriptor and make it reference both
- * the inode representing the portal and the call director
- * socket for the portal.
- */
- fp = falloc();
- if (fp == NULL)
- goto bad2;
- fp->f_flag = FPORTAL|FSOCKET;
- fp->f_inode = ip;
- fp->f_socket = so;
-
- /*
- * Make the in-core inode reference the socket.
- */
- ip->i_un.i_socket = so;
- irele(ip);
- return;
-bad2:
- err = u.u_error;
- iput(ip);
- u.u_dirp = ap->name;
- unlink();
- u.u_error = err;
-bad:
- sofree(so);
-}
-
-/*
- * Splice system call interface.
- */
-ssplice()
-{
- register struct a {
- int fd1;
- int fd2;
- } *ap = (struct a *)u.u_ap;
- struct file *f1, *f2;
- struct socket *pso, *pso2;
-
- f1 = getf(ap->fd1);
- if (f1 == NULL)
- return;
- f2 = getf(ap->fd2);
- if (f2 == NULL)
- return;
- if ((f1->f_flag & FSOCKET) == 0 || (f2->f_flag & FSOCKET) == 0) {
- u.u_error = ENOTSOCK;
- return;
- }
- if (f1->f_count > 1 || f2->f_count > 1) {
- u.u_error = ETOOMANYREFS;
- return;
- }
- u.u_error = pi_splice(f1->f_socket, f2->f_socket);
- if (u.u_error)
- return;
- u.u_ofile[ap->fd1] = 0;
- u.u_ofile[ap->fd2] = 0;
- f1->f_count = 0;
- f2->f_count = 0;
-}
-
-/*
- * Socket system call interface. Copy in arguments
+ * Socket system call interface. Copy sa arguments
* set up file descriptor and call internal socket
* creation routine.
*/
{
register struct a {
int type;
- struct in_addr *ain;
+ struct sockproto *asp;
+ struct sockaddr *asa;
int options;
} *uap = (struct a *)u.u_ap;
- struct in_addr in;
- struct socket *so0;
+ struct sockproto sp;
+ struct sockaddr sa;
+ struct socket *so;
register struct file *fp;
+COUNT(SSOCKET);
if ((fp = falloc()) == NULL)
return;
fp->f_flag = FSOCKET|FREAD|FWRITE;
- if (copyin((caddr_t)uap->ain, &in, sizeof (in))) {
+ 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;
return;
}
- u.u_error = socket(&so0, uap->type, &in, uap->options);
+ u.u_error = socreate(&so, uap->type,
+ uap->asp ? &sp : 0, uap->asa ? &sa : 0, uap->options);
if (u.u_error)
goto bad;
- fp->f_socket = so0;
+ fp->f_socket = so;
return;
bad:
u.u_ofile[u.u_r.r_val1] = 0;
fp->f_count = 0;
}
+
/*
- * Connect socket to foreign peer; system call
- * interface. Copy in arguments and call internal routine.
+ * Accept system call interface.
*/
-sconnect()
+saccept()
{
register struct a {
- int fdes;
- struct in_addr *a;
+ int fdes;
+ struct sockaddr *asa;
} *uap = (struct a *)u.u_ap;
- in_addr in;
+ struct sockaddr sa;
register struct file *fp;
- register struct socket *so;
+ struct socket *so;
int s;
+COUNT(SACCEPT);
- if (copyin((caddr_t)uap->a, &in, sizeof (in))) {
+ if (uap->asa && useracc((caddr_t)uap->asa, sizeof (sa), B_WRITE)==0) {
u.u_error = EFAULT;
return;
}
u.u_error = ENOTSOCK;
return;
}
- so = fp->f_socket;
- u.u_error = connect(so, &in);
- if (u.u_error)
- return;
s = splnet();
- if ((so->so_options & SO_NBIO) &&
- (so->so_state & SS_ISCONNECTING)) {
- u.u_error = EINPROGRESS;
+ so = fp->f_socket;
+ if ((so->so_state & SS_NBIO) &&
+ (so->so_state & SS_CONNAWAITING) == 0) {
+ u.u_error = EWOULDBLOCK;
splx(s);
return;
}
- while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
+ while ((so->so_state & SS_CONNAWAITING) == 0 && so->so_error == 0) {
+ if (so->so_state & SS_CANTRCVMORE) {
+ so->so_error = ECONNABORTED;
+ break;
+ }
sleep((caddr_t)&so->so_timeo, PZERO+1);
- u.u_error = so->so_error;
- so->so_error = 0;
+ }
+ if (so->so_error) {
+ u.u_error = so->so_error;
+ splx(s);
+ return;
+ }
+ u.u_error = soaccept(so, &sa);
+ if (u.u_error) {
+ splx(s);
+ return;
+ }
+ if (uap->asa)
+ (void) copyout((caddr_t)&sa, (caddr_t)uap->asa, sizeof (sa));
+ /* deal with new file descriptor case */
+ /* u.u_r.r_val1 = ... */
splx(s);
}
/*
- * Disconnect socket from foreign peer; system call
- * interface. Copy in arguments and call internal routine.
+ * Connect socket to foreign peer; system call
+ * interface. Copy sa arguments and call internal routine.
*/
-sdisconnect()
+sconnect()
{
register struct a {
int fdes;
- in_addr *addr;
+ struct sockaddr *a;
} *uap = (struct a *)u.u_ap;
- in_addr in;
+ struct sockaddr sa;
register struct file *fp;
register struct socket *so;
int s;
+COUNT(SCONNECT);
- if (uap->addr &&
- copyin((caddr_t)uap->addr, (caddr_t)&in, sizeof (in))) {
+ if (copyin((caddr_t)uap->a, (caddr_t)&sa, sizeof (sa))) {
u.u_error = EFAULT;
return;
}
return;
}
so = fp->f_socket;
- u.u_error = disconnect(so, uap->addr ? &in : 0);
+ u.u_error = soconnect(so, &sa);
if (u.u_error)
return;
s = splnet();
- if ((so->so_options&SO_NBIO) && (so->so_state&SS_ISDISCONNECTING)) {
+ if ((so->so_state & SS_NBIO) &&
+ (so->so_state & SS_ISCONNECTING)) {
u.u_error = EINPROGRESS;
splx(s);
return;
}
- while (so->so_state & SS_ISDISCONNECTING)
+ 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;
{
register struct a {
int fdes;
- in_addr *ain;
+ struct sockaddr *asa;
caddr_t cbuf;
- int count;
+ unsigned count;
} *uap = (struct a *)u.u_ap;
register struct file *fp;
- struct in_addr in;
+ struct sockaddr sa;
+COUNT(SSEND);
fp = getf(uap->fdes);
if (fp == 0)
u.u_error = ENOTSOCK;
return;
}
- if (uap->count < 0) {
- u.u_error = EINVAL;
- return;
- }
u.u_base = uap->cbuf;
u.u_count = uap->count;
u.u_segflg = 0;
if (useracc(uap->cbuf, uap->count, B_READ) == 0 ||
- uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) {
+ uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
u.u_error = EFAULT;
return;
}
- u.u_error = send(fp->f_socket, uap->ain ? &in : 0);
+ u.u_error = sosend(fp->f_socket, uap->asa ? &sa : 0);
+ u.u_r.r_val1 = uap->count - u.u_count;
}
/*
{
register struct a {
int fdes;
- in_addr *ain;
+ struct sockaddr *asa;
caddr_t cbuf;
- int count;
+ u_int count;
} *uap = (struct a *)u.u_ap;
register struct file *fp;
- struct in_addr *in;
+ struct sockaddr sa;
+COUNT(SRECEIVE);
fp = getf(uap->fdes);
if (fp == 0)
u.u_error = ENOTSOCK;
return;
}
- if (uap->count < 0) {
- u.u_error = EINVAL;
- return;
- }
u.u_base = uap->cbuf;
u.u_count = uap->count;
u.u_segflg = 0;
if (useracc(uap->cbuf, uap->count, B_WRITE) == 0 ||
- uap->ain && copyin((caddr_t)uap->ain, (caddr_t)&in, sizeof (in))) {
+ uap->asa && copyin((caddr_t)uap->asa, (caddr_t)&sa, sizeof (sa))) {
u.u_error = EFAULT;
return;
}
- receive(fp->f_socket, uap->ain ? &in : 0);
+ u.u_error = soreceive(fp->f_socket, uap->asa ? &sa : 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 - u.u_count;
+}
+
+/*
+ * Get socket address.
+ */
+ssocketaddr()
+{
+ register struct a {
+ int fdes;
+ struct sockaddr *asa;
+ } *uap = (struct a *)u.u_ap;
+ register struct file *fp;
+ register struct socket *so;
+ struct sockaddr addr;
+COUNT(SSOCKETADDR);
+
+ fp = getf(uap->fdes);
+ if (fp == 0)
+ return;
+ if ((fp->f_flag & FSOCKET) == 0) {
+ u.u_error = ENOTSOCK;
+ return;
+ }
+ so = fp->f_socket;
+ u.u_error =
+ (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, (caddr_t)&addr);
+ if (u.u_error)
+ return;
+ if (copyout((caddr_t)&addr, (caddr_t)uap->asa, sizeof (addr)))
+ u.u_error = EFAULT;
}