+ int domain;
+ int type;
+ int protocol;
+ int *rsv;
+ } *uap = (struct a *)u.u_ap;
+ register struct file *fp1, *fp2;
+ struct socket *so1, *so2;
+ int sv[2];
+
+ if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) {
+ u.u_error = EFAULT;
+ return;
+ }
+ u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol);
+ if (u.u_error)
+ return;
+ u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol);
+ if (u.u_error)
+ goto free;
+ fp1 = falloc();
+ if (fp1 == NULL)
+ goto free2;
+ sv[0] = u.u_r.r_val1;
+ fp1->f_flag = FREAD|FWRITE;
+ fp1->f_type = DTYPE_SOCKET;
+ fp1->f_ops = &socketops;
+ fp1->f_data = (caddr_t)so1;
+ fp2 = falloc();
+ if (fp2 == NULL)
+ goto free3;
+ fp2->f_flag = FREAD|FWRITE;
+ fp2->f_type = DTYPE_SOCKET;
+ fp2->f_ops = &socketops;
+ fp2->f_data = (caddr_t)so2;
+ sv[1] = u.u_r.r_val1;
+ u.u_error = soconnect2(so1, so2);
+ if (u.u_error)
+ goto free4;
+ (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
+ return;
+free4:
+ fp2->f_count = 0;
+ u.u_ofile[sv[1]] = 0;
+free3:
+ fp1->f_count = 0;
+ u.u_ofile[sv[0]] = 0;
+free2:
+ so2->so_state |= SS_NOFDREF;
+ sofree(so2);
+free:
+ so1->so_state |= SS_NOFDREF;
+ sofree(so1);
+}
+
+sendto()
+{
+ register struct a {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ caddr_t to;
+ int tolen;
+ } *uap = (struct a *)u.u_ap;
+ struct msghdr msg;
+ struct iovec aiov;
+
+ msg.msg_name = uap->to;
+ msg.msg_namelen = uap->tolen;
+ msg.msg_iov = &aiov;
+ msg.msg_iovlen = 1;
+ aiov.iov_base = uap->buf;
+ aiov.iov_len = uap->len;
+ msg.msg_accrights = 0;
+ msg.msg_accrightslen = 0;
+ sendit(uap->s, &msg, uap->flags);
+}
+
+send()
+{
+ register struct a {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ } *uap = (struct a *)u.u_ap;
+ struct msghdr msg;
+ struct iovec aiov;
+
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &aiov;
+ msg.msg_iovlen = 1;
+ aiov.iov_base = uap->buf;
+ aiov.iov_len = uap->len;
+ msg.msg_accrights = 0;
+ msg.msg_accrightslen = 0;
+ sendit(uap->s, &msg, uap->flags);
+}
+
+sendmsg()
+{
+ register struct a {
+ int s;
+ caddr_t msg;
+ int flags;
+ } *uap = (struct a *)u.u_ap;
+ struct msghdr msg;
+ struct iovec aiov[MSG_MAXIOVLEN];
+
+ u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
+ if (u.u_error)
+ return;
+ if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
+ u.u_error = EMSGSIZE;
+ return;
+ }
+ u.u_error =
+ copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
+ (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
+ if (u.u_error)
+ return;
+ msg.msg_iov = aiov;
+#ifdef notdef
+printf("sendmsg name %x namelen %d iov %x iovlen %d accrights %x &len %d\n",
+msg.msg_name, msg.msg_namelen, msg.msg_iov, msg.msg_iovlen,
+msg.msg_accrights, msg.msg_accrightslen);
+#endif
+ sendit(uap->s, &msg, uap->flags);
+}
+
+sendit(s, mp, flags)
+ int s;
+ register struct msghdr *mp;
+ int flags;
+{
+ register struct file *fp;
+ struct uio auio;
+ register struct iovec *iov;
+ register int i;
+ struct mbuf *to, *rights;
+ int len;
+
+ fp = getsock(s);
+ if (fp == 0)
+ return;
+ auio.uio_iov = mp->msg_iov;
+ auio.uio_iovcnt = mp->msg_iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_offset = 0; /* XXX */
+ auio.uio_resid = 0;
+ iov = mp->msg_iov;
+ for (i = 0; i < mp->msg_iovlen; i++) {
+ if (iov->iov_len < 0) {
+ u.u_error = EINVAL;
+ return;
+ }
+ if (iov->iov_len == 0)
+ continue;
+ if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) {
+ u.u_error = EFAULT;
+ return;
+ }
+ auio.uio_resid += iov->iov_len;
+ iov++;
+ }
+ if (mp->msg_name) {
+ u.u_error =
+ sockargs(&to, mp->msg_name, mp->msg_namelen);
+ if (u.u_error)
+ return;
+ } else
+ to = 0;
+ if (mp->msg_accrights) {
+ u.u_error =
+ sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen);
+ if (u.u_error)
+ goto bad;
+ } else
+ rights = 0;
+ len = auio.uio_resid;
+ u.u_error =
+ sosend((struct socket *)fp->f_data, to, &auio, flags, rights);
+ u.u_r.r_val1 = len - auio.uio_resid;
+ if (rights)
+ m_freem(rights);
+bad:
+ if (to)
+ m_freem(to);
+}
+
+recvfrom()
+{
+ register struct a {
+ int s;
+ caddr_t buf;
+ int len;
+ int flags;
+ caddr_t from;
+ int *fromlenaddr;