Changeset View
Changeset View
Standalone View
Standalone View
head/sys/compat/linux/linux_socket.c
Show First 20 Lines • Show All 1,257 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr, | linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr, | ||||
l_uint flags, struct msghdr *msg) | l_uint flags, struct msghdr *msg) | ||||
{ | { | ||||
struct cmsghdr *cm; | struct cmsghdr *cm; | ||||
struct cmsgcred *cmcred; | struct cmsgcred *cmcred; | ||||
struct l_cmsghdr *linux_cmsg = NULL; | struct l_cmsghdr *linux_cmsg = NULL; | ||||
struct l_ucred linux_ucred; | struct l_ucred linux_ucred; | ||||
socklen_t datalen, outlen; | socklen_t datalen, maxlen, outlen; | ||||
struct l_msghdr linux_msg; | struct l_msghdr linux_msg; | ||||
struct iovec *iov, *uiov; | struct iovec *iov, *uiov; | ||||
struct mbuf *control = NULL; | struct mbuf *control = NULL; | ||||
struct mbuf **controlp; | struct mbuf **controlp; | ||||
struct timeval *ftmvl; | struct timeval *ftmvl; | ||||
l_timeval ltmvl; | l_timeval ltmvl; | ||||
caddr_t outbuf; | caddr_t outbuf; | ||||
void *data; | void *data; | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | if (error != 0) | ||||
goto bad; | goto bad; | ||||
} | } | ||||
if (linux_msg.msg_name && linux_msg.msg_namelen > 2) { | if (linux_msg.msg_name && linux_msg.msg_namelen > 2) { | ||||
error = linux_sa_put(PTRIN(linux_msg.msg_name)); | error = linux_sa_put(PTRIN(linux_msg.msg_name)); | ||||
if (error != 0) | if (error != 0) | ||||
goto bad; | goto bad; | ||||
} | } | ||||
outbuf = PTRIN(linux_msg.msg_control); | maxlen = linux_msg.msg_controllen; | ||||
outlen = 0; | linux_msg.msg_controllen = 0; | ||||
if (control) { | if (control) { | ||||
linux_cmsg = malloc(L_CMSG_HDRSZ, M_LINUX, M_WAITOK | M_ZERO); | linux_cmsg = malloc(L_CMSG_HDRSZ, M_LINUX, M_WAITOK | M_ZERO); | ||||
msg->msg_control = mtod(control, struct cmsghdr *); | msg->msg_control = mtod(control, struct cmsghdr *); | ||||
msg->msg_controllen = control->m_len; | msg->msg_controllen = control->m_len; | ||||
cm = CMSG_FIRSTHDR(msg); | cm = CMSG_FIRSTHDR(msg); | ||||
outbuf = PTRIN(linux_msg.msg_control); | |||||
outlen = 0; | |||||
while (cm != NULL) { | while (cm != NULL) { | ||||
linux_cmsg->cmsg_type = | linux_cmsg->cmsg_type = | ||||
bsd_to_linux_cmsg_type(cm->cmsg_type); | bsd_to_linux_cmsg_type(cm->cmsg_type); | ||||
linux_cmsg->cmsg_level = | linux_cmsg->cmsg_level = | ||||
bsd_to_linux_sockopt_level(cm->cmsg_level); | bsd_to_linux_sockopt_level(cm->cmsg_level); | ||||
if (linux_cmsg->cmsg_type == -1 | if (linux_cmsg->cmsg_type == -1 || | ||||
|| cm->cmsg_level != SOL_SOCKET) | cm->cmsg_level != SOL_SOCKET) { | ||||
{ | |||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
data = CMSG_DATA(cm); | data = CMSG_DATA(cm); | ||||
datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; | datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; | ||||
switch (cm->cmsg_type) | switch (cm->cmsg_type) { | ||||
{ | |||||
case SCM_RIGHTS: | case SCM_RIGHTS: | ||||
if (flags & LINUX_MSG_CMSG_CLOEXEC) { | if (flags & LINUX_MSG_CMSG_CLOEXEC) { | ||||
fds = datalen / sizeof(int); | fds = datalen / sizeof(int); | ||||
fdp = data; | fdp = data; | ||||
for (i = 0; i < fds; i++) { | for (i = 0; i < fds; i++) { | ||||
fd = *fdp++; | fd = *fdp++; | ||||
(void)kern_fcntl(td, fd, | (void)kern_fcntl(td, fd, | ||||
F_SETFD, FD_CLOEXEC); | F_SETFD, FD_CLOEXEC); | ||||
Show All 28 Lines | while (cm != NULL) { | ||||
ftmvl = (struct timeval *)data; | ftmvl = (struct timeval *)data; | ||||
ltmvl.tv_sec = ftmvl->tv_sec; | ltmvl.tv_sec = ftmvl->tv_sec; | ||||
ltmvl.tv_usec = ftmvl->tv_usec; | ltmvl.tv_usec = ftmvl->tv_usec; | ||||
data = <mvl; | data = <mvl; | ||||
datalen = sizeof(ltmvl); | datalen = sizeof(ltmvl); | ||||
break; | break; | ||||
} | } | ||||
if (outlen + LINUX_CMSG_LEN(datalen) > | if (outlen + LINUX_CMSG_LEN(datalen) > maxlen) { | ||||
linux_msg.msg_controllen) { | |||||
if (outlen == 0) { | if (outlen == 0) { | ||||
error = EMSGSIZE; | error = EMSGSIZE; | ||||
goto bad; | goto bad; | ||||
} else { | } else { | ||||
linux_msg.msg_flags |= | linux_msg.msg_flags |= LINUX_MSG_CTRUNC; | ||||
LINUX_MSG_CTRUNC; | m_dispose_extcontrolm(control); | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen); | linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen); | ||||
error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ); | error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ); | ||||
if (error != 0) | if (error != 0) | ||||
goto bad; | goto bad; | ||||
outbuf += L_CMSG_HDRSZ; | outbuf += L_CMSG_HDRSZ; | ||||
error = copyout(data, outbuf, datalen); | error = copyout(data, outbuf, datalen); | ||||
if (error != 0) | if (error != 0) | ||||
goto bad; | goto bad; | ||||
outbuf += LINUX_CMSG_ALIGN(datalen); | outbuf += LINUX_CMSG_ALIGN(datalen); | ||||
outlen += LINUX_CMSG_LEN(datalen); | outlen += LINUX_CMSG_LEN(datalen); | ||||
cm = CMSG_NXTHDR(msg, cm); | cm = CMSG_NXTHDR(msg, cm); | ||||
} | } | ||||
linux_msg.msg_controllen = outlen; | |||||
} | } | ||||
out: | out: | ||||
linux_msg.msg_controllen = outlen; | |||||
error = copyout(&linux_msg, msghdr, sizeof(linux_msg)); | error = copyout(&linux_msg, msghdr, sizeof(linux_msg)); | ||||
bad: | bad: | ||||
free(iov, M_IOV); | if (control != NULL) { | ||||
if (error != 0) | |||||
m_dispose_extcontrolm(control); | |||||
m_freem(control); | m_freem(control); | ||||
} | |||||
free(iov, M_IOV); | |||||
free(linux_cmsg, M_LINUX); | free(linux_cmsg, M_LINUX); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) | linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 323 Lines • Show Last 20 Lines |