int kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) { struct socket *so; struct file *fp; cap_rights_t rights; int error; AUDIT_ARG_FD(fd); AUDIT_ARG_SOCKADDR(td, dirfd, sa); error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND), &fp, NULL, NULL); if (error != 0) return (error); so = fp->f_data; #ifdef KTRACE if (KTRPOINT(td, KTR_STRUCT)) ktrsockaddr(sa); #endif #ifdef MAC error = mac_socket_check_bind(td->td_ucred, so, sa); if (error == 0) { #endif if (dirfd == AT_FDCWD) error = sobind(so, sa, td); else error = sobindat(dirfd, so, sa, td); #ifdef MAC } #endif fdrop(fp, td); return (error); }
/* ARGSUSED */ int sys_bind(struct proc *p, void *v, register_t *retval) { struct sys_bind_args /* { syscallarg(int) s; syscallarg(const struct sockaddr *) name; syscallarg(socklen_t) namelen; } */ *uap = v; struct file *fp; struct mbuf *nam; int error; if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) return (error); error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), MT_SONAME); if (error == 0) { #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); #endif error = sobind(fp->f_data, nam, p); m_freem(nam); } FRELE(fp, p); return (error); }
/* ARGSUSED */ int sys_connect(struct proc *p, void *v, register_t *retval) { struct sys_connect_args /* { syscallarg(int) s; syscallarg(const struct sockaddr *) name; syscallarg(socklen_t) namelen; } */ *uap = v; struct file *fp; struct socket *so; struct mbuf *nam = NULL; int error, s; if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0) return (error); so = fp->f_data; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { FRELE(fp, p); return (EALREADY); } error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen), MT_SONAME); if (error) goto bad; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen)); #endif error = soconnect(so, nam); if (error) goto bad; if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) { FRELE(fp, p); m_freem(nam); return (EINPROGRESS); } s = splsoftnet(); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { error = tsleep(&so->so_timeo, PSOCK | PCATCH, "netcon2", 0); if (error) break; } if (error == 0) { error = so->so_error; so->so_error = 0; } splx(s); bad: so->so_state &= ~SS_ISCONNECTING; FRELE(fp, p); if (nam) m_freem(nam); if (error == ERESTART) error = EINTR; return (error); }
void ktrstruct(char *buf, size_t buflen) { char *name, *data; size_t namelen, datalen; int i; for (name = buf, namelen = 0; namelen < buflen && name[namelen] != '\0'; ++namelen) /* nothing */; if (namelen == buflen) goto invalid; if (name[namelen] != '\0') goto invalid; data = buf + namelen + 1; datalen = buflen - namelen - 1; if (datalen == 0) goto invalid; /* sanity check */ for (i = 0; i < namelen; ++i) if (!isalpha((unsigned char)name[i])) goto invalid; if (strcmp(name, "stat") == 0) { struct stat sb; if (datalen != sizeof(struct stat)) goto invalid; memcpy(&sb, data, datalen); ktrstat(&sb); } else if (strcmp(name, "sockaddr") == 0) { struct sockaddr_storage ss; if (datalen > sizeof(ss)) goto invalid; memcpy(&ss, data, datalen); if ((ss.ss_family != AF_UNIX && datalen < sizeof(struct sockaddr)) || datalen != ss.ss_len) goto invalid; ktrsockaddr((struct sockaddr *)&ss); } else if (strcmp(name, "abstimespec") == 0 || strcmp(name, "reltimespec") == 0) { struct timespec ts; if (datalen != sizeof(ts)) goto invalid; memcpy(&ts, data, datalen); ktrtimespec(&ts, name[0] == 'r'); } else if (strcmp(name, "abstimeval") == 0 || strcmp(name, "reltimeval") == 0) { struct timeval tv; if (datalen != sizeof(tv)) goto invalid; memcpy(&tv, data, datalen); ktrtimeval(&tv, name[0] == 'r'); } else if (strcmp(name, "sigaction") == 0) { struct sigaction sa; if (datalen != sizeof(sa)) goto invalid; memcpy(&sa, data, datalen); ktrsigaction(&sa); } else if (strcmp(name, "rlimit") == 0) { struct rlimit lim; if (datalen != sizeof(lim)) goto invalid; memcpy(&lim, data, datalen); ktrrlimit(&lim); } else if (strcmp(name, "rusage") == 0) { struct rusage ru; if (datalen != sizeof(ru)) goto invalid; memcpy(&ru, data, datalen); ktrrusage(&ru); } else if (strcmp(name, "tfork") == 0) { struct __tfork tf; if (datalen != sizeof(tf)) goto invalid; memcpy(&tf, data, datalen); ktrtfork(&tf); } else if (strcmp(name, "fdset") == 0) { struct fd_set *fds; if ((fds = malloc(datalen)) == NULL) err(1, "malloc"); memcpy(fds, data, datalen); ktrfdset(fds, datalen); free(fds); } else { printf("unknown structure %s\n", name); } return; invalid: printf("invalid record\n"); }
int recvit(struct proc *p, int s, struct msghdr *mp, caddr_t namelenp, register_t *retsize) { struct file *fp; struct uio auio; struct iovec *iov; int i; size_t len; int error; struct mbuf *from = NULL, *control = NULL; #ifdef KTRACE struct iovec *ktriov = NULL; #endif if ((error = getsock(p->p_fd, s, &fp)) != 0) return (error); auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_READ; auio.uio_procp = p; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { /* Don't allow sum > SSIZE_MAX */ if (iov->iov_len > SSIZE_MAX || (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { error = EINVAL; goto out; } } #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) { int iovlen = auio.uio_iovcnt * sizeof (struct iovec); ktriov = malloc(iovlen, M_TEMP, M_WAITOK); bcopy(auio.uio_iov, ktriov, iovlen); } #endif len = auio.uio_resid; error = soreceive(fp->f_data, &from, &auio, NULL, mp->msg_control ? &control : NULL, &mp->msg_flags, mp->msg_control ? mp->msg_controllen : 0); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } #ifdef KTRACE if (ktriov != NULL) { if (error == 0) ktrgenio(p, s, UIO_READ, ktriov, len - auio.uio_resid); free(ktriov, M_TEMP); } #endif if (error) goto out; *retsize = len - auio.uio_resid; if (mp->msg_name) { socklen_t alen; if (from == NULL) alen = 0; else { alen = from->m_len; error = copyout(mtod(from, caddr_t), mp->msg_name, MIN(alen, mp->msg_namelen)); if (error) goto out; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(from, caddr_t), alen); #endif } mp->msg_namelen = alen; if (namelenp && (error = copyout(&alen, namelenp, sizeof(alen)))) { goto out; } } if (mp->msg_control) { len = mp->msg_controllen; if (len <= 0 || control == NULL) len = 0; else { struct mbuf *m = control; caddr_t p = mp->msg_control; do { i = m->m_len; if (len < i) { mp->msg_flags |= MSG_CTRUNC; i = len; } error = copyout(mtod(m, caddr_t), p, i); if (m->m_next) i = ALIGN(i); p += i; len -= i; if (error != 0 || len <= 0) break; } while ((m = m->m_next) != NULL); len = p - (caddr_t)mp->msg_control; } mp->msg_controllen = len; } if (!error) { fp->f_rxfer++; fp->f_rbytes += *retsize; } out: FRELE(fp, p); if (from) m_freem(from); if (control) m_freem(control); return (error); }
int sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize) { struct file *fp; struct uio auio; struct iovec *iov; int i; struct mbuf *to, *control; size_t len; int error; #ifdef KTRACE struct iovec *ktriov = NULL; #endif to = NULL; if ((error = getsock(p->p_fd, s, &fp)) != 0) return (error); auio.uio_iov = mp->msg_iov; auio.uio_iovcnt = mp->msg_iovlen; auio.uio_segflg = UIO_USERSPACE; auio.uio_rw = UIO_WRITE; auio.uio_procp = p; auio.uio_offset = 0; /* XXX */ auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { /* Don't allow sum > SSIZE_MAX */ if (iov->iov_len > SSIZE_MAX || (auio.uio_resid += iov->iov_len) > SSIZE_MAX) { error = EINVAL; goto bad; } } if (mp->msg_name) { error = sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME); if (error) goto bad; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrsockaddr(p, mtod(to, caddr_t), mp->msg_namelen); #endif } if (mp->msg_control) { if (mp->msg_controllen < CMSG_ALIGN(sizeof(struct cmsghdr))) { error = EINVAL; goto bad; } error = sockargs(&control, mp->msg_control, mp->msg_controllen, MT_CONTROL); if (error) goto bad; } else control = 0; #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) { int iovlen = auio.uio_iovcnt * sizeof (struct iovec); ktriov = malloc(iovlen, M_TEMP, M_WAITOK); bcopy(auio.uio_iov, ktriov, iovlen); } #endif len = auio.uio_resid; error = sosend(fp->f_data, to, &auio, NULL, control, flags); if (error) { if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; if (error == EPIPE && (flags & MSG_NOSIGNAL) == 0) ptsignal(p, SIGPIPE, STHREAD); } if (error == 0) { *retsize = len - auio.uio_resid; fp->f_wxfer++; fp->f_wbytes += *retsize; } #ifdef KTRACE if (ktriov != NULL) { if (error == 0) ktrgenio(p, s, UIO_WRITE, ktriov, *retsize); free(ktriov, M_TEMP); } #endif bad: FRELE(fp, p); if (to) m_freem(to); return (error); }