/* * Get peer socket name. */ int do_sys_getpeername(int fd, struct mbuf **nam) { struct socket *so; struct mbuf *m; int error; if ((error = fd_getsock(fd, &so)) != 0) return error; m = m_getclr(M_WAIT, MT_SONAME); MCLAIM(m, so->so_mowner); solock(so); if ((so->so_state & SS_ISCONNECTED) == 0) error = ENOTCONN; else { *nam = m; error = (*so->so_proto->pr_usrreqs->pr_peeraddr)(so, m); } sounlock(so); if (error != 0) m_free(m); fd_putfile(fd); return error; }
static int kttcp_recv(struct lwp *l, struct kttcp_io_args *kio) { struct socket *so; int error; struct timeval t0, t1; unsigned long long len, done; done = 0; /* XXX gcc */ if (kio->kio_totalsize > KTTCP_MAX_XMIT) return EINVAL; if ((error = fd_getsock(kio->kio_socket, &so)) != 0) return error; len = kio->kio_totalsize; microtime(&t0); do { error = kttcp_soreceive(so, len, &done, l, NULL); len -= done; } while (error == 0 && len > 0 && done > 0); fd_putfile(kio->kio_socket); microtime(&t1); if (error == EPIPE) error = 0; if (error != 0) return error; timersub(&t1, &t0, &kio->kio_elapsed); kio->kio_bytesdone = kio->kio_totalsize - len; return 0; }
int do_sys_connect(struct lwp *l, int fd, struct mbuf *nam) { struct socket *so; int error; int interrupted = 0; if ((error = fd_getsock(fd, &so)) != 0) { m_freem(nam); return (error); } solock(so); MCLAIM(nam, so->so_mowner); if ((so->so_state & SS_ISCONNECTING) != 0) { error = EALREADY; goto out; } error = soconnect(so, nam, l); if (error) goto bad; if ((so->so_state & (SS_NBIO|SS_ISCONNECTING)) == (SS_NBIO|SS_ISCONNECTING)) { error = EINPROGRESS; goto out; } while ((so->so_state & SS_ISCONNECTING) != 0 && so->so_error == 0) { error = sowait(so, true, 0); if (__predict_false((so->so_state & SS_ISABORTING) != 0)) { error = EPIPE; interrupted = 1; break; } if (error) { if (error == EINTR || error == ERESTART) interrupted = 1; break; } } if (error == 0) { error = so->so_error; so->so_error = 0; } bad: if (!interrupted) so->so_state &= ~SS_ISCONNECTING; if (error == ERESTART) error = EINTR; out: sounlock(so); fd_putfile(fd); m_freem(nam); return error; }
int do_sys_recvmsg(struct lwp *l, int s, struct msghdr *mp, struct mbuf **from, struct mbuf **control, register_t *retsize) { int error; struct socket *so; if ((error = fd_getsock(s, &so)) != 0) return error; error = do_sys_recvmsg_so(l, s, so, mp, from, control, retsize); fd_putfile(s); return error; }
int sys_listen(struct lwp *l, const struct sys_listen_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(int) backlog; } */ struct socket *so; int error; if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) return (error); error = solisten(so, SCARG(uap, backlog), l); fd_putfile(SCARG(uap, s)); return error; }
int do_sys_bind(struct lwp *l, int fd, struct mbuf *nam) { struct socket *so; int error; if ((error = fd_getsock(fd, &so)) != 0) { m_freem(nam); return (error); } MCLAIM(nam, so->so_mowner); error = sobind(so, nam, l); m_freem(nam); fd_putfile(fd); return error; }
int sys_shutdown(struct lwp *l, const struct sys_shutdown_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(int) how; } */ struct socket *so; int error; if ((error = fd_getsock(SCARG(uap, s), &so)) != 0) return error; solock(so); error = soshutdown(so, SCARG(uap, how)); sounlock(so); fd_putfile(SCARG(uap, s)); return error; }
/* * Get local socket name. */ int do_sys_getsockname(int fd, struct mbuf **nam) { struct socket *so; struct mbuf *m; int error; if ((error = fd_getsock(fd, &so)) != 0) return error; m = m_getclr(M_WAIT, MT_SONAME); MCLAIM(m, so->so_mowner); *nam = m; solock(so); error = (*so->so_proto->pr_usrreqs->pr_sockaddr)(so, m); sounlock(so); if (error != 0) m_free(m); fd_putfile(fd); return error; }
int recvit32(struct lwp *l, int s, struct netbsd32_msghdr *mp, struct iovec *iov, void *namelenp, register_t *retsize) { struct uio auio; int i, len, error, iovlen; struct mbuf *from = 0, *control = 0; struct socket *so; struct proc *p; struct iovec *ktriov = NULL; p = l->l_proc; /* fd_getsock() will use the descriptor for us */ if ((error = fd_getsock(s, &so)) != 0) return (error); auio.uio_iov = iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_rw = UIO_READ; auio.uio_vmspace = l->l_proc->p_vmspace; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; for (i = 0; i < mp->msg_iovlen; i++, iov++) { #if 0 /* cannot happen iov_len is unsigned */ if (iov->iov_len < 0) { error = EINVAL; goto out1; } #endif /* * Reads return ssize_t because -1 is returned on error. * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ auio.uio_resid += iov->iov_len; if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { error = EINVAL; goto out1; } } if (ktrpoint(KTR_GENIO)) { iovlen = auio.uio_iovcnt * sizeof(struct iovec); ktriov = (struct iovec *)malloc(iovlen, M_TEMP, M_WAITOK); memcpy((void *)ktriov, (void *)auio.uio_iov, iovlen); } len = auio.uio_resid; error = (*so->so_receive)(so, &from, &auio, NULL, NETBSD32PTR64(mp->msg_control) ? &control : NULL, &mp->msg_flags); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } if (ktriov != NULL) { ktrgeniov(s, UIO_READ, ktriov, len - auio.uio_resid, error); FREE(ktriov, M_TEMP); } if (error) goto out; *retsize = len - auio.uio_resid; if (NETBSD32PTR64(mp->msg_name)) { len = mp->msg_namelen; if (len <= 0 || from == 0) len = 0; else { if (len > from->m_len) len = from->m_len; /* else if len < from->m_len ??? */ error = copyout(mtod(from, void *), (void *)NETBSD32PTR64(mp->msg_name), (unsigned)len); if (error) goto out; } mp->msg_namelen = len; if (namelenp && (error = copyout((void *)&len, namelenp, sizeof(int)))) goto out; }
int sys_recvmmsg(struct lwp *l, const struct sys_recvmmsg_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(struct mmsghdr *) mmsg; syscallarg(unsigned int) vlen; syscallarg(unsigned int) flags; syscallarg(struct timespec *) timeout; } */ struct mmsghdr mmsg; struct socket *so; struct msghdr *msg = &mmsg.msg_hdr; int error, s; struct mbuf *from, *control; struct timespec ts, now; unsigned int vlen, flags, dg; if (SCARG(uap, timeout)) { if ((error = copyin(SCARG(uap, timeout), &ts, sizeof(ts))) != 0) return error; getnanotime(&now); timespecadd(&now, &ts, &ts); } s = SCARG(uap, s); if ((error = fd_getsock(s, &so)) != 0) return error; vlen = SCARG(uap, vlen); if (vlen > 1024) vlen = 1024; from = NULL; flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; for (dg = 0; dg < vlen;) { error = copyin(SCARG(uap, mmsg) + dg, &mmsg, sizeof(mmsg)); if (error) break; msg->msg_flags = flags & ~MSG_WAITFORONE; if (from != NULL) { m_free(from); from = NULL; } error = do_sys_recvmsg_so(l, s, so, msg, &from, msg->msg_control != NULL ? &control : NULL, retval); if (error) { if (error == EAGAIN && dg > 0) error = 0; break; } if (msg->msg_control != NULL) error = copyout_msg_control(l, msg, control); if (error) break; error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0, from); if (error) break; ktrkuser("msghdr", msg, sizeof *msg); mmsg.msg_len = *retval; error = copyout(&mmsg, SCARG(uap, mmsg) + dg, sizeof(mmsg)); if (error) break; dg++; if (msg->msg_flags & MSG_OOB) break; if (SCARG(uap, timeout)) { getnanotime(&now); timespecsub(&now, &ts, &now); if (now.tv_sec > 0) break; } if (flags & MSG_WAITFORONE) flags |= MSG_DONTWAIT; } if (from != NULL) m_free(from); *retval = dg; if (error) so->so_error = error; fd_putfile(s); /* * If we succeeded at least once, return 0, hopefully so->so_error * will catch it next time. */ if (dg) return 0; return error; }
int ultrix_sys_setsockopt(struct lwp *l, const struct ultrix_sys_setsockopt_args *uap, register_t *retval) { struct sockopt sopt; struct socket *so; int error; struct sys_setsockopt_args ap; SCARG(&ap, s) = SCARG(uap, s); SCARG(&ap, level) = SCARG(uap, level); SCARG(&ap, name) = SCARG(uap, name); SCARG(&ap, val) = SCARG(uap, val); SCARG(&ap, valsize) = SCARG(uap, valsize); /* fd_getsock() will use the descriptor for us */ if ((error = fd_getsock(SCARG(&ap, s), &so)) != 0) return error; #define SO_DONTLINGER (~SO_LINGER) if (SCARG(&ap, name) == SO_DONTLINGER) { struct linger lg; lg.l_onoff = 0; error = so_setsockopt(l, so, SCARG(&ap, level), SO_LINGER, &lg, sizeof(lg)); goto out; } if (SCARG(&ap, level) == IPPROTO_IP) { #define EMUL_IP_MULTICAST_IF 2 #define EMUL_IP_MULTICAST_TTL 3 #define EMUL_IP_MULTICAST_LOOP 4 #define EMUL_IP_ADD_MEMBERSHIP 5 #define EMUL_IP_DROP_MEMBERSHIP 6 static const int ipoptxlat[] = { IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP }; if (SCARG(&ap, name) >= EMUL_IP_MULTICAST_IF && SCARG(&ap, name) <= EMUL_IP_DROP_MEMBERSHIP) { SCARG(&ap, name) = ipoptxlat[SCARG(&ap, name) - EMUL_IP_MULTICAST_IF]; } } if (SCARG(&ap, valsize) > MLEN) { error = EINVAL; goto out; } sockopt_init(&sopt, SCARG(&ap, level), SCARG(&ap, name), SCARG(&ap, valsize)); if (SCARG(&ap, val)) { error = copyin(SCARG(&ap, val), sopt.sopt_data, (u_int)SCARG(&ap, valsize)); } if (error == 0) error = sosetopt(so, &sopt); sockopt_destroy(&sopt); out: fd_putfile(SCARG(uap, s)); return error; }